自从我去年开始学习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设计模式的例子及其功能对等物吗?
正如公认的答案所说,OOP和FP都有其特定的模式。
然而,有一些模式是非常常见的,我能想到的所有编程平台都应该有。以下是一个(不完整的)列表:
Adapter. I can hardly think of a useful programming platform which is so comprehensive (and self-fulfilled) that it does not need to talk to the world. If it is going to do so, an adapter is definitely needed.
Façade. Any programming platforms that can handle big source code should be able to modularise. If you were to create a module for other parts of the program, you will want to hide the "dirty" parts of the code and give it a nice interface.
Interpreter. In general, any program is just doing two things: parse input and print output. Mouse inputs need to be parsed, and window widgets need to be printed out. Therefore, having an embedded interpreter gives the program additional power to customise things.
另外,我注意到在典型的FP语言Haskell中,有一些类似于GoF模式的东西,但名称不同。在我看来,这表明它们存在,因为在FP和OOP语言中都有一些共同的问题需要解决。
单子转换器和装饰器。前者用于向现有的单子中添加额外的能力,后者用于向现有的对象中添加额外的能力。
函数式编程消除了对面向对象设计模式的需求这一说法是否属实?
函数式编程与面向对象编程不同。面向对象的设计模式不适用于函数式编程。取而代之的是函数式编程设计模式。
对于函数式编程,您不需要阅读面向对象设计模式书籍;你会读到其他关于FP设计模式的书籍。
语言无关的
不完全。对于面向对象语言,只有语言不可知。这种设计模式根本不适用于过程式语言。它们在关系数据库设计上下文中几乎没有意义。它们不适用于设计电子表格。
一个典型的OOP设计模式和它的功能对等物?
上述情况不应该存在。这就像要求将一段过程代码重写为OO代码。嗯……如果我将原始的Fortran(或C)翻译成Java,我所做的只是翻译它。如果我完全将其重写为面向对象范式,它将不再看起来像原始的Fortran或C语言——它将无法识别。
从面向对象设计到功能设计没有简单的映射。他们看问题的方式完全不同。
函数式编程(像所有编程风格一样)具有设计模式。关系数据库有设计模式,OO有设计模式,过程式编程有设计模式。任何事物都有设计模式,甚至是建筑物的结构。
设计模式——作为一个概念——是一种永恒的构建方式,与技术或问题领域无关。但是,特定的设计模式适用于特定的问题领域和技术。
每个人只要仔细思考自己在做什么,就会发现设计模式。
正如其他人所说,函数式编程有特定的模式。我认为摆脱设计模式的问题与其说是转换到功能的问题,不如说是语言特性的问题。
看看Scala是如何废除“单例模式”的:只需声明一个对象而不是一个类。
另一个特性,模式匹配,有助于避免笨重的访问者模式。对比如下:
Scala的模式匹配=类固醇访问者模式
Scala和f#一样,是OO-functional的融合。我不了解f#,但它可能有这些特性。
闭包是在函数式语言中出现的,但不需要被限制在函数式语言中。它们有助于使用委托模式。
还有一个观察结果。这段代码实现了一个模式:它是如此经典,如此基本,以至于我们通常不认为它是一个“模式”,但它确实是:
for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }
像Java和c#这样的命令式语言已经采用了本质上是一个函数结构来处理这个问题:“foreach”。