自从我去年开始学习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中作为用例适配器(如cleanarch和ddd)的适配器模式可以通过Option的单变量在Functional中实现。

你不是在取代他们,而是在改造他们。

其他回答

当你试着从“设计模式”(一般)和“FP vs . OOP”的层面来看待这个问题时,你会发现答案最多是模糊的。

但是,在这两个轴上深入研究,并考虑特定的设计模式和特定的语言功能,事情就会变得更清楚。

因此,例如,当使用具有代数数据类型和模式匹配、闭包、第一类函数等的语言时,一些特定的模式(如访问者、策略、命令和观察者)肯定会改变或消失。不过,GoF书中的其他一些模式仍然“存在”。

总的来说,我会说,随着时间的推移,特定的模式正在被新的(或正在流行的)语言特性所淘汰。这是语言设计的自然过程;随着语言变得越来越高级,以前只能在书中使用示例来调用的抽象现在成为特定语言特性或库的应用程序。

(顺便说一句:这是我最近写的一篇博客,上面有更多关于FP和设计模式讨论的链接。)

Peter Norvig的《动态编程中的设计模式》(Design Patterns in Dynamic Programming)对这一主题进行了深入的讨论,不过他讲的是“动态”语言而不是“函数式”语言(两者有重叠)。

这是另一个讨论这个话题的链接:http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

在他的博客文章中,Edward用Haskell描述了所有23种原始的GoF模式。

我认为只有两个GoF设计模式是用来将函数式编程逻辑引入自然的面向对象语言的。我想到了《战略与指挥》。 其他一些GoF设计模式可以通过函数式编程进行修改,以简化设计并保持目的。

讨论这个问题时不能不提到类型系统。

函数式编程的主要特征包括函数作为第一类值、curry化、不可变值等。在我看来,OO设计模式是否接近这些特性并不明显。

这是因为这些特性不能解决OOP所解决的问题……它们是命令式编程的替代品。面向对象的FP答案在于ML和Haskell的类型系统……特别是和类型、抽象数据类型、ML模块和Haskell类型类。

当然,仍然有一些设计模式是FP语言无法解决的。FP与单例的等价是什么?(暂时不考虑单例对象通常是一种糟糕的模式)

类型类做的第一件事是消除对单例对象的需求。

你可以浏览这23个名单,然后再剔除更多,但我现在没有时间。