Design patterns 要避免的设计模式

Design patterns 要避免的设计模式,design-patterns,anti-patterns,Design Patterns,Anti Patterns,很多人似乎都同意,单身模式有很多缺点,有些人甚至建议完全避免这种模式。这里有一个。请将有关单例模式的任何评论指向该问题 我的问题:还有其他设计模式需要避免或小心使用吗?我相信观察者模式有很多问题需要回答,它在非常普遍的情况下工作,但随着系统变得越来越复杂,它成了一场噩梦,需要OnBefore()和OnAfter()通知,并且经常发布异步任务以避免重新进入。一个更好的解决方案是开发一个自动依赖性分析系统,在计算期间对所有对象访问(带有读取障碍)进行检测,并在依赖关系图中自动创建一条边。我认为模板方

很多人似乎都同意,单身模式有很多缺点,有些人甚至建议完全避免这种模式。这里有一个。请将有关单例模式的任何评论指向该问题


我的问题:还有其他设计模式需要避免或小心使用吗?

我相信观察者模式有很多问题需要回答,它在非常普遍的情况下工作,但随着系统变得越来越复杂,它成了一场噩梦,需要OnBefore()和OnAfter()通知,并且经常发布异步任务以避免重新进入。一个更好的解决方案是开发一个自动依赖性分析系统,在计算期间对所有对象访问(带有读取障碍)进行检测,并在依赖关系图中自动创建一条边。

我认为模板方法模式通常是一种非常危险的模式

  • 很多时候,它会因为“错误的原因”而耗尽您的继承层次结构
  • 基类有被各种不相关的代码弄乱的趋势
  • 它迫使您锁定设计,通常是在开发过程的早期。(在许多情况下过早锁定)
  • 在以后的阶段改变这一点变得越来越困难

我认为活动记录是一种过度使用的模式,它鼓励将业务逻辑和持久性代码混合在一起。它不能很好地从模型层隐藏存储实现,并将模型绑定到数据库。有很多替代方案(在PoEAA中描述),如表数据网关、行数据网关和数据映射器,它们通常提供更好的解决方案,当然也有助于提供更好的存储抽象。此外,您的模型不需要存储在数据库中;如何将它们存储为XML或使用web服务访问它们?更改型号的存储机制有多容易

也就是说,Active Record并不总是坏的,它非常适合于其他选项过于复杂的简单应用程序。

模式非常复杂 应小心使用所有设计模式。在我看来,如果有充分的理由这样做,而不是立即实现模式。使用模式的一般问题是它们增加了复杂性。过度使用模式会使给定的应用程序或系统难以进一步开发和维护

大多数情况下,有一个简单的解决方案,您不需要应用任何特定的模式。一个好的经验法则是,每当代码片段倾向于被替换或需要经常更改时,就使用模式,并且在使用模式时准备好接受复杂代码的警告

记住这一点,如果您认为实际需要支持代码中的更改,请使用一种模式

原则胜过模式 如果模式显然会导致过度设计和复杂的解决方案,那么使用模式似乎是一种没有实际意义的做法。然而,对于程序员来说,读取设计技巧和原则是非常有趣的,这为大多数模式奠定了基础。事实上,我的一项建议是重申哪些原则适用于所讨论的模式。它们足够简单,在相关性方面比模式有用。其中一些原则足够通用,可以涵盖更多面向对象编程(OOP),例如,只要您可以构建代码模块

有许多设计原则,但中描述的这些原则在开始时非常有用

  • 程序是“接口”,而不是“实现”。(四人帮1995:18)
  • 喜欢“对象组合”而不是“类继承”。(四人帮1995:20)
让这些东西在你身上停留一段时间。应该注意的是,当编写GoF时,它意味着任何抽象的东西(也意味着超级类),不要与Java或C#中作为类型的接口混淆。第二个原则来自于观察到的过度使用继承,这是一个错误

从那里你可以读到罗伯特·塞西尔·马丁的作品。Scott Hanselman在一次采访中采访了Bob叔叔:

  • S单一责任原则
  • O笔闭合原理
  • Liskov代换原理
  • I界面隔离原则
  • D依附性反转原理

这些原则是一个很好的开端,可以让你与同龄人一起阅读和讨论。您可能会发现这些原则相互交织,并与其他过程(如和)交织在一起。在做了一段时间之后,你可能会发现这些原则在实践中很自然,因为你需要在一定程度上遵循它们,以创建独立且可重复的单元测试。

这是对斯波克文章的补充,是一本很好的读物。

单例-使用单例X的类对它有依赖性,很难看到,也很难隔离以进行测试

它们经常被使用,因为它们方便且易于理解,但它们确实会使测试复杂化


看。

我希望我不会因此而被打得太多。Christer Ericsson在他的著作中写了两篇关于设计模式的文章(,)。他的语气相当刺耳,也许有点挑衅性,但这个人知道他的东西,所以我不会认为这是疯子的胡言乱语。

我不认为你应该避免设计模式(DP),我也不认为你应该在规划架构时强迫自己使用DPs。我们应该只在我们的规划中自然出现DPs时才使用DPs

如果我们从一开始就定义要使用给定的DP,那么我们未来的许多设计决策将受到该选择的影响,无法保证我们选择的DP适合我们的需要

我们也不应该做的一件事是将DP视为一个不变的实体,我们应该根据我们的需要调整模式

所以,sumarizing,我喜欢
interface IShape
{
    double intersectWith(Triangle t);
    double intersectWith(Rectangle r);
    double intersectWith(Circle c);
}
interface IShape
{
    Area getArea();
}

class Area
{
    public double intersectWith(Area otherArea);
    ...
}