自从我去年开始学习f#和OCaml以来,我已经阅读了大量的文章,这些文章坚持认为设计模式(尤其是Java中的)是命令式语言中缺失特性的变通方法。我发现的一篇文章给出了相当有力的主张:
Most people I've met have read
the Design Patterns book by the Gang of
Four (GoF). Any self respecting programmer
will tell you that the book is
language agnostic and the patterns
apply to software engineering in
general, regardless of which language
you use. This is a noble claim.
Unfortunately it is far removed from
the truth.
Functional languages are extremely
expressive. In a functional language
one does not need design patterns
because the language is likely so high
level, you end up programming in
concepts that eliminate design
patterns all together.
函数式编程(FP)的主要特性包括函数作为一类值、curry化、不可变值等。在我看来,OO设计模式是否接近这些特性并不明显。
此外,在支持OOP的函数式语言(如f#和OCaml)中,使用这些语言的程序员显然会使用与其他OOP语言相同的设计模式。事实上,现在我每天都在使用f#和OCaml,我在这些语言中使用的模式与我在Java中使用的模式之间没有明显的区别。
函数式编程消除了对面向对象设计模式的需求这一说法是否属实?如果是这样的话,你能发布或链接到一个典型的OOP设计模式的例子及其功能对等物吗?
布莱恩关于语言和模式之间紧密联系的评论很中肯,
The missing part of this discussion is the concept of idiom. James O. Coplien's book, "Advanced C++" was a huge influence here. Long before he discovered Christopher Alexander and the Column Without a Name (and you can't talk sensibly about patterns without reading Alexander either), he talked about the importance of mastering idioms in truly learning a language. He used string copy in C as an example, while(*from++ = *to++); You can see this as a bandaid for a missing language feature (or library feature), but what really matters about it is that it's a larger unit of thought, or of expression, than any of its parts.
这就是模式和语言试图做的,让我们更简洁地表达我们的意图。思想的单位越丰富,你能表达的思想就越复杂。从系统架构到琐碎小事,在不同的范围内拥有丰富的、共享的词汇,可以让我们进行更明智的对话,并思考我们应该做什么。
作为个体,我们也可以学习。这就是练习的意义所在。我们每个人都能理解和使用我们自己永远无法想到的东西。语言、框架、库、模式、习语等等都在共享知识财富中占有一席之地。
当你试着从“设计模式”(一般)和“FP vs . OOP”的层面来看待这个问题时,你会发现答案最多是模糊的。
但是,在这两个轴上深入研究,并考虑特定的设计模式和特定的语言功能,事情就会变得更清楚。
因此,例如,当使用具有代数数据类型和模式匹配、闭包、第一类函数等的语言时,一些特定的模式(如访问者、策略、命令和观察者)肯定会改变或消失。不过,GoF书中的其他一些模式仍然“存在”。
总的来说,我会说,随着时间的推移,特定的模式正在被新的(或正在流行的)语言特性所淘汰。这是语言设计的自然过程;随着语言变得越来越高级,以前只能在书中使用示例来调用的抽象现在成为特定语言特性或库的应用程序。
(顺便说一句:这是我最近写的一篇博客,上面有更多关于FP和设计模式讨论的链接。)
正如其他人所说,函数式编程有特定的模式。我认为摆脱设计模式的问题与其说是转换到功能的问题,不如说是语言特性的问题。
看看Scala是如何废除“单例模式”的:只需声明一个对象而不是一个类。
另一个特性,模式匹配,有助于避免笨重的访问者模式。对比如下:
Scala的模式匹配=类固醇访问者模式
Scala和f#一样,是OO-functional的融合。我不了解f#,但它可能有这些特性。
闭包是在函数式语言中出现的,但不需要被限制在函数式语言中。它们有助于使用委托模式。
还有一个观察结果。这段代码实现了一个模式:它是如此经典,如此基本,以至于我们通常不认为它是一个“模式”,但它确实是:
for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }
像Java和c#这样的命令式语言已经采用了本质上是一个函数结构来处理这个问题:“foreach”。