自从我至少在10年前首次了解“四人一组”(GoF)设计模式以来,我一直以为这23种模式应该只是更大的东西的小样本,我称之为模式空间。这个假设的模式空间由针对常见的面向对象软件设计问题的所有推荐解决方案(已知或未知)组成。

所以我希望已知和记录的设计模式的数量会大大增加。

没有发生。 GoF书问世20多年后,维基百科文章中仅列出了12种其他模式,其中大多数都不如原始模式流行。 (我未在其中包含并发模式,因为它们涉及特定主题。)

原因是什么?


GoF模式集实际上更多吗?
是否发现新模式的兴趣下降了,也许是因为发现它们在软件设计中并不是那么有用吗?
还有其他事情吗? br />

评论

模式无处不在,但通常以无味和机器人化的方式使用它们。因此,我认为模式目录的想法变得不那么流行了。

设计空间?统计,有人将Mark Rosewater带到这里!

马丁·福勒(Martin Fowler)在2003年发表了《企业应用程序架构的模式》,记录了大约50种模式,其中许多模式在今天仍然可以很好地重新构造和很好地使用,例如。 “数据映射器”,“插件”,“延迟加载”,“服务层”等。

探索所有可能模式的空间就像根本不探索可能模式的空间。您可以使所有内容成为一种模式。如果您将所有内容都设为模式,那么什么都不是模式,因为单词失去了它的含义。
@BradThomas:当然,像最有趣的问题一样,人们倾向于有一定的见解。但是,观点至少部分基于事实,我在此问题的答案中发现了许多有趣的事实,这些事实将有助于我自己,并希望其他人重新思考他们的观点并获得更多依据。

#1 楼

当《书》问世时,很多人都这样想,并且为创建“模式库”甚至“模式社区”付出了很多努力。您仍然可以找到其中的一些:



“样式社区”,WikiWikiWeb

“纽约市设计模式研究组”,工业逻辑


The Hillside Group的“模式目录”


,然后...


寻找新模式的兴趣下降了吗,也许是因为它们在软件设计中并没有那么有用吗?设计模式的重点是改善开发人员之间的沟通,但是,如果您尝试添加更多的模式,则会很快达到人们不记得他们,忘记它们,或者就他们的真实面貌达成不同意见的程度。实际上没有改善。就GoF模式而言,这已经发生了很多。

我个人将走得更远:软件设计(尤其是好的软件设计)相差太大,无法在模式中有意义地体现出来,尤其是在小型模式人们实际上可以记住的模式数量-而且它们太抽象了,人们无法真正记住很多模式。因此,他们没有太大帮助。

太多的人迷上了这个概念,并试图将模式应用于任何地方–通常,在生成的代码中,您无法在所有(完全无意义的)单例和抽象工厂之间找到实际的设计。

评论


有争议的意见:无论如何,抽象工厂是一种代码异味:)

– MetaFight
16年11月12日在16:20

也许是有争议的观点,但是表达起来非常重要。设计模式有可能成为皇帝新衣服的典范,在那里我们所有人都不敢质疑它们是否有用。做得好。

– David Arno
16年11月12日在19:39

@MetaFight ControversialialDesignPatternOnlineOpinionHumanReadableRetortFactory.newInstance()。getText();

– corsiKa
16年11月13日在8:08

“设计模式的重点是改善开发人员之间的沟通”我认为设计模式是为了解决开发人员通常(而且通常是独立地)遇到的问题。标准改善了沟通,由于波动(由于XY问题而产生的图案,图案被视为反图案),许多人不认为设计图案是标准。设计模式擅长指出语言功能的不足,我相信语言设计师会在解决这些问题之前将其变为设计模式。不过不要相信我

–二恶英
16年11月13日在20:19

@ChrisW我看不出你的意思...正如我说的,GoF试图克服OO的缺点,尤其是C ++ 98的缺点,因为这是他们与Smalltalk一起选择的语言。他们实际上写道:“编程语言的选择很重要,因为它会影响一个人的观点。我们的模式假定使用Smalltalk / C ++级别的语言功能,而这种选择决定了可以轻松实现的内容。”

– Shautieh
16年11月14日下午3:36

#2 楼


我的印象是,这23种模式应该只是较大的东西的小样本,我喜欢将其称为模式空间。


初学者程序员到处传播它,认为自己仅通过将软件模式结合在一起就可以编写程序的程序员。那样行不通。如果存在这样的“模式空间”,则可以假定其大小实际上是无限的。

设计模式(在GoF意义上)仅具有一个目的:补偿您所使用的编程语言的不足。正在使用。

设计模式既不通用也不全面。如果更改为其他更具表达性的编程语言,GoF书中的大多数模式将变得既不必要又令人讨厌。

评论


“设计模式(在GoF意义上)仅具有一个目的:弥补您所使用的编程语言的不足。”我一直在听,但是还没有看到有道理。每种假设的辩解都指向少数几个具有某些功能的语言更容易实现的模式(通常是Visitor或Singleton),并且使绝大多数模式保持不变,这意味着它们也可以通过以下方式变得多余更好的语言。但是我们怎么知道?哪种语言功能使观察者无关紧要?责任链?综合?

–法律
16年11月12日在19:54

@Jules仅一流的功能就消除了它们的相当大的一部分,包括责任链(它只是功能列表的组合)。功能性反应式编程消除了观察者模式。 Composite模式只是对monoid的较不严格的定义,具有类型类并且关注代数律的语言为使用monoid提供了强大的工具。我可以列出更多,但您知道了。

–杰克
16-11-13在0:10



@Jules:我相信原始的GoF书将迭代器作为一种模式列出,但是现在,它在每种OOP远程语言中的语言功能转换已基本完成。

–凯文
16-11-13在5:25

@RubberDuck如何使样式已经实现而使样式过时?仍然是正在实施的设计模式。语言功能的不同集合可能导致模式的不同实现,但是模式本身仍然存在。通过为常用的重复策略命名,可以简化模式以进行沟通。以防万一,.NET类称为ObservableSomething ,由于它使用了众所周知的模式名称,因此易于理解它们的用途。模式是一个想法,而不是确切的实现。

–空
16年11月13日在12:06

@Jules:什么是程序?重现问题的解决方案。什么是设计模式?重现问题的解决方案。为什么不是程序?因为我们无法将其表示为程序。因此,设计模式是针对重复出现的问题的解决方案,该问题应该是程序而不是设计模式,而不能是程序,因为该语言的表达能力不足以表达该程序。示例:不久前,“子例程调用”是一种设计模式!如今,它是一种语言功能。

–‐Jörg W Mittag
16-11-14在8:04



#3 楼

我认为这里涉及三个因素。

临界质量不足

首先,模式基本上只不过是为一些实现功能的特定“块”。名称提供真正价值的唯一方法是,如果您可以依靠每个人都知道名称的含义,那么仅通过使用名称,他们就可以立即对代码有很多了解。他们需要达到临界质量。相反,AAMOF。自GoF书问世以来的20年来,我很确定我没有看到多达十二次对话,每个参与其中的人都真正了解足够的设计模式以用于改善沟通。 >
说得有点古怪:设计模式失败是因为它们失败了。

模式太多了

我认为第二个主要因素是,如果有的话,他们最初命名的模式过多。在相当多的情况下,模式之间的差异非常细微,以至于几乎无法确切地说出某个特定类别是否适合一种模式或另一种模式(或者可能适合两种模式,或者可能两者都不适用)。 />目的是您可以在更高层次上讨论代码。您可以将相当大的代码块标记为特定模式的实现。只需使用该预定义的名称,每个倾听的人通常都会对他们所关心的代码有足够的了解,因此您可以继续进行下一步。现实往往恰恰相反。假设您正在开会,并告诉他们这个特定的班级是一个Facade。会议中有一半的人不知道或者早就忘记了那是什么意思。其中之一要求您提醒他,门面与代理之间的确切区别。哦,这几位真正了解模式的人在会议的其余时间中讨论了是否应将其真正视为门面还是“仅仅是”适配器(那个家伙仍然坚持认为对他来说似乎是代理人)。

鉴于您的意图实际上只是在说:“这段代码不是很有趣;让我们继续前进”,尝试使用模式名称只会增加注意力,而不是价值。 >
缺乏兴趣

大多数设计模式并未真正处理有趣的代码部分。他们处理诸如:“如何创建这些对象?”和“如何使该对象与那个对象对话?”这样的问题。记住这些的模式名称(以及前面提到的有关细节之类的论点)只是为大多数程序员不太在意的事情投入了很多精力。 :模式处理许多程序之间的相同问题,但是真正使程序变得有趣的是它与其他程序的不同之处。失败的原因是:


它们不能达到临界质量。
模式之间的差异不足以保证清晰度。
它们主要处理几乎没有人真正关心的代码部分无论如何。


评论


“ ...但是真正使程序变得有趣的是它与其他程序的不同之处。”我完全同意,但是为此您必须首先正确处理相同的部分,也许它们只是在一些琐碎的方面有所不同。如果您放松一点,则需要说出名称和识别模式,我相信几乎每个人都会看到模式。只是它们几乎永远不会以其纯粹的形式出现,而是总是或多或少地适应当前的问题。

– Trilarion
16-11-14在11:55

很好的答案。

–罗伯特·哈维(Robert Harvey)
16年11月14日在16:01

@Trilarion:哦,我知道必须编写代码的那些部分。例如,它们有点像您汽车上的轮胎。您几乎完全需要轮胎来驱动-但是大多数人仍然几乎不知道汽车上轮胎的品牌。这要求他们为带有不对称斜槽的轮胎学习特殊术语。谁知道-那些人可能曾经救过我一次命,但我仍然不花我的一生为他们学习名字。

–杰里·科芬(Jerry Coffin)
16年11月14日在22:04

@DavidRicherby:好的,让我们使用“生产者方面”的比喻。为固特异公司设计轮胎的约翰在该类型的凹槽中使用一个单词,但为米其林工作的皮埃尔使用一个完全不同的单词是否重要?一个人只使用一个凹槽,而另一个人使用一个完整的轮胎,该轮胎在中心一侧有水平凹槽,而在另一侧有对角凹槽,这有关系吗?

–杰里·科芬(Jerry Coffin)
16年11月16日在14:51

@immibis:我大多会说,他们失败了。我要说的是,大多数程序员识别的模式只有不到六种。 Singleton是众所周知的,但实际上很少适用(最多)。在“模式”出现之前很久就使用了“工厂”这个名称(我记得它在1970年代末或1980年代初使用)。模式应该被用来形成词汇,但是目前它们就像我的希腊语词汇一样-足以(可能)使自己陷入困境,但肯定不足以下单,更不用说进行有意义的对话了。

–杰里·科芬(Jerry Coffin)
18年1月10日在1:17



#4 楼

模式丢失了抽象,抽象了简单的模式,复杂的模式未被识别,因此模式没有用(除了一些高级模式)。当我在程序中看到模式时,我认为这是麻烦的迹象。程序的形状应仅反映需要解决的问题。至少对我来说,代码中的其他任何规律性都是一个信号,即我正在使用不够强大的抽象-通常是我手工生成需要编写的某些宏的扩展。 />
当您识别代码中的模式时,这意味着某些内容会重复出现,因此您应该使用更好的抽象。如果没有更好的抽象,则可以使用该模式作为解决方法。因为更新的编程语言提供了更好的抽象,所以模式的用途就大大减少了。
简单的模式通常也很容易抽象,而复杂的模式则很少被认识。
当模式被抽象替换时,并不意味着模式后面的概念消失了,但可以显式地编写该概念而不是间接地编写该概念,并且与其他代码相比,它不再特殊,并且不再可以识别为模式。

评论


我个人确实很喜欢这个主意。但是,代码应该像模式一样被人类和人们可读。模式可以帮助我们找到解决方法。从我们的代码中删除所有模式将使其不可读。

–弗兰克·普弗(Frank Puffer)
16-11-13在11:58



@Frank我认为PG的来源是模式是您可以抽象的底层函数的“气味”,而您没有将其提取到函数或宏中就是导致重复的原因-就像如果没有String.replace函数,您可以想象它会以一种模式弹出,但是最好只编写一次,而不是继续重新实现它。同意如果您没有正确命名这些名称,将使其更难阅读,但是正确完成后,代码将以更具声明性的方式读取IMO(例如,选项monads的getOrElse样式与null检查)

–otherdave
16年11月13日在13:21

保罗·格雷厄姆(Paul Graham)的报价是关于保持解决方案干燥的,这不同于GoF“模式”的想法。 GoF的想法是为常用的解决方案命名。在GoF发布他们的书之前,我们已经做了那么久。例如,我可以告诉我的同事我要使用队列,而我的同事可以立即知道我在说什么,而不必解释队列的作用或工作原理的细节。但是,请参见上面的迈克尔·伯格沃德(Michael Borgwardt)的出色答案。

–所罗门慢
16年11月13日在19:46



我认为,这个答案误解了什么是模式。设计模式是常见问题的常见解决方案。这不是一些代码重复。假设有一个迭代器。您解决了将容器抽象化的问题,因此无论容器是什么,都可以遍历其中的元素。因此,您将创建一个迭代器类,该迭代器类为每个容器执行此操作,并使它们实现一个公共接口。这里要抽象什么?迭代器已经是一个抽象。而且,当然,所有容器的实现方式都不同,因此没有代码重复。

–马尔科姆
16年11月14日在9:10

Graham引用的关键部分通常是我手工生成一些我需要编写的宏扩展。这专门引用了Lisp宏。没有宏,只能做这么多抽象。

–巴特·范·尼罗普
16-11-14在12:43

#5 楼

尽管我在很大程度上同意其他人在此处回答的内容,但我个人认为,模式数量没有增长的主要原因是,当存在无数模式时,模式就会失去其含义。这几种模式的好处是,它们以标准方式涵盖了很多问题领域。如果您专注于无休止的图案领域,那么您最终将根本没有任何图案。有点像“一个岛的海岸线有多长?”。如果在地图上测量,您会得到一个不错的数字。但是,如果您尝试获得更高的精确度并获得更高的分辨率,您会发现长度越来越多地达到无穷大(或不确定性;您将如何在潮汐和原子水平上测量精确的边界?)。

评论


是的,模式只有在模式太多时才能起作用。但是为什么GoF仍然是最受欢迎的?现在,许多人(Singleton,Builder等)将其中的一些视为反模式。这应该为新的,更有用的模式腾出空间,而不增加总数。

–弗兰克·普弗(Frank Puffer)
16-11-13在11:14



我想这就像十诫。源仅2个字符(GIF,GOE,GOD)xD

– qwerty_soda
16年11月13日在11:18

是的,有时候现代软件工程似乎与GoF有关,就像中世纪的学者与Aristotle有关。

–弗兰克·普弗(Frank Puffer)
16年11月13日在11:30

#6 楼

其他答案中没有一个也与之相关:

动态类型语言的兴起。

当这本书问世时,人们就开始认真讨论Java是太慢了,无法进行真正的工作。现在,由于Java的速度,它经常被使用在更具表现力的语言上。对于某些重要的应用程序类来说,也许Ruby,Python,JavaScript等仍然太慢了,但总的来说,它们对于大多数用途来说足够快。而且,尽管每个版本中都有更多功能,但JavaScript至少实际上正在变得更快。有时如此。经典设计模式的某些功能实际上是向静态类型的系统中添加动态功能的方式(例如已经讨论过的AbstractFactory,您可以在其中基于运行时数据实例化正确的类)。其他人在动态语言中要短得多,以至于他们只是简单地融入了语言本身的惯用用法。

#7 楼

确实发生了。出版了数十本甚至数百本的书,这似乎是试图将整个计算机科学简化为设计模式,因为出版商和作者都试图跳入(或创造)另一种潮流。我有一个架子。自从第一次扫描以来从未咨询过,是的,我是个傻瓜,因为其中几乎没有或没有任何实际用途,或者尚不为人所知(例如,参见Type Object,它不过是表示为一打而不是一个段落),并且因为模式越少越好:这是大多数实践者无法理解的一点。确实,当我发表对Type Object的反驳时,我被指示要重铸我的文本作为一种设计模式。真实的故事。这也显示了该项目的另一个缺陷:没有审查,排除或拒绝机制。

事实上,GOF实际上并没有尝试“彻底探索设计模式”。相反,他们从事的是一个更大的项目:将“模式语言”引入CS,以其所有奇异的符号化的力量,参与者等奥秘名言,只是失败了,因为它从根本上被误解了,而且毫无意义。

他们完成的工作非常有用,有两件事:


发布一些有用的技巧,例如Visitor模式
提供标准集基本上被卡住的名称:工厂,适配器,迭代器... ...如果您看一下事先设计好的CORBA,您将看到它的价值:各种“外国”名称,例如拦截器,仆人,经纪人,...

另一个有用的概念是“反模式”,例如“记录并抛出”。与CS的许多时尚一样,该项目因其自身的传福音和被误导为另一种CS宗教而脱轨,并且沿袭了大多数此类宗教的方式:在某些方面有用,但肯定是``没有灵丹妙药''( (弗雷德·布鲁克斯,1965年)。不幸的是我们必须每隔几年才重新发现它。

评论


如果它引发了这场讨论(还包括所有这些内容),是否仍然难过?

– r3wt
17年7月24日在21:31



@ r3wt非sequitur。我很难过的是,IT行业的弱点在于认为每个新开发都将成为神话般的灵丹妙药,并且偶然地浪费了一些自己的先前工作。

–user207421
17年7月24日在23:06

从不同的角度来看它。对我来说,阅读您的答案,学会不重蹈覆辙并不难过。因此,您认为理所当然的事情对其他人非常有用。

– r3wt
17年7月25日在0:43

#8 楼

有几本名为PLoP(程序设计的模式语言)的书,每本书都是在年度会议上发表的论文选集。

读这些书,我发现其中的一些模式有趣而新颖。对我来说,其中一些是标准的(例如“半对象加协议”)。

“维基百科文章中仅列出了12个其他模式”可能也不是完整的集合:即,其他地方也记录了其他模式,例如在PLoP书籍中,也许也在其他地方。

评论


是的,如果您搜索数百种模式,则可以找到它们的描述。但是这些似乎都没有像GoF那样受欢迎。

–弗兰克·普弗(Frank Puffer)
16年11月13日在10:54

这是因为我喜欢阅读GoF书籍,所以在出版(后来)时,我会阅读更多(书籍)。

– ChristW
16年11月13日在11:07

@FrankPuffer我敢打赌,这些模式很流行,即使名称不是。

–装饰
16年11月15日在8:47

#9 楼

《四人帮(Gang of Four,GoF)》一书包含了大多数模式,这些模式是经验丰富的无功能语言程序员在其工具带中拥有的。就像所有构建者都知道如何使用的基本工具集一样。本书的主要贡献是为当时大多数有经验的程序员常用的模式赋予明确的名称,从而帮助讨论设计方案的程序员之间进行交流。

您希望电工拥有一些普通建造者所没有的工具,同样,您希望WPF程序员知道“依赖属性”或“ SQL程序员”的设计模式。知道使用触发器创建审计数据的设计模式。

由于它们仅与一种技术一起使用,因此我们不将其视为“设计模式”。

更多现代设计模式书是“重构,改进现有代码的设计(马丁·福勒)”和“清洁代码:敏捷软件技巧手册(罗伯特·C·马丁)”,这两本书都将内容介绍为您的转变对您当前的代码进行修改,而不是将其作为“预定义的可重用设计”,但是它们同样是“设计模式”。

#10 楼

这是对Erich Gamma的一次采访,他在其中回顾了模式的选择以及今天它们的变化(直到10年前的今天,哈哈)。 com / articles / article.aspx?p = 1404056


Larry:您将如何重构“设计模式”?

Erich:我们在2005年做了此练习这是我们会议的一些笔记。从那时起,我们发现面向对象的设计原理和大多数模式都没有改变。我们想要更改分类,添加一些新成员,并删除一些模式。大多数讨论都是关于更改类别,尤其是要删除的模式。

当讨论要删除的模式时,我们发现我们仍然喜欢它们。 (不完全是,我赞成删除Singleton。它的使用几乎总是一种设计上的味道。)

因此,这里有一些更改: >解释器和Flyweight应该移到一个单独的类别中,我们称之为“其他/化合物”,因为它们实际上是与其他样式不同的野兽。工厂方法将被通用化为工厂。
类别为:核心,创新,外围和其他。这里的目的是强调重要的模式,并将其与不常用的模式分开。
新成员是:Null对象,类型对象,依赖注入和扩展对象/接口(请参见程序设计的模式语言3,Addison-Wesley,1997年。)这些类别:


核心:复合,策略,状态,命令,迭代器,代理,模板方法,外观
创新的:工厂,原型,生成器,依赖注入
外围的:抽象工厂,访客,装饰器,介体,类型对象,空对象,扩展对象
其他:Flyweight,解释器





评论


你为什么要不赞成我请在评论中解释,以便我改善答案。

–akuaku
16 Dec 23 '19:07

#11 楼

本书中的实际模式有时确实很有用,但实际上它们只是本书为您提供的功能更强大的工具的一个实例:对何时何地深入将整体代码切成由接口分隔和控制的独立部分更好的理解。

当您学习该技能时,您会意识到您无需记住每个模式的确切细节,因为您始终可以以最适合其方式的方式削减正在实施的解决方案目的。因此,写下越来越多的模式的想法似乎非常学术和毫无意义。

评论


好点,但是,我怀疑许多人都以这种方式理解这本书(或一般的模式)。

–弗兰克·普弗(Frank Puffer)
17年1月26日在12:29

@ lud1977如果我们不记录历史,那么什么能防止未来陷入同样的​​陷阱?因此,必须始终对其进行记录。它不是没有意义的。

– r3wt
17年7月24日在21:35

#12 楼


因此,我希望已知的和记录在案的设计模式数量会大大增加。

这没有发生。 GoF书问世20多年后,
Wikipedia文章中仅列出了12种其他模式,其中大多数
都比原始模式流行得多。 (我没有在这里包含并发模式,因为它们涵盖了特定的
主题。)


GoF书和Wikipedia并不是已知设计的唯一来源模式。如果您仅在Amazon.com中搜索“设计模式”,则可以获得数百本书(尝试此搜索)。我猜他们只列出了Wikipedia文章中最著名的模式。

所以问题不在于没有足够的书面设计模式。而是有太多的东西,没有人能记住全部,而且大多数程序员只能认出其中的几个。通用模式语言的巨大前景在这一点上被打破。

#13 楼

可能尚未想到很多结构。只要人们在开发软件,就会面临设计挑战。其中一些可以使用其他人可以利用的聪明的新模式来解决。这些模式在语言设计中仍然存在。因此,今天它们可能会被忽略,但这并不会使它们变得不重要。

一旦有了可以为我们做的机器人,如何建造房屋的知识就突然变得不重要了吗?我会说不,不是。这没那么重要,可以肯定-由于需求确实急剧下降,而且没有人在研究它,因此学习的好处可能更少。

所以,不,我不相信您的模式空间称它已经筋疲力尽。另一个答案指出,它可能是无限的。但是随着对系统设计需求的下降,随着我们增加抽象塔的高度和编程语言的力量-越来越少的高层建筑人员将关注塔的建造细节。

#14 楼

模式是无限的。您可以调整每个模式或将n个匹配项混合以创建新的模式。.企业集成模式也得到了很好的定义。每个领域的模式都会演变,它们也会随着诸如python或scala之类的表达语言而发生变化。.