您引用的博客文章夸大了其声明。FP并没有消除对设计模式的需求。术语“设计模式”只是没有被广泛用于在FP语言中描述同一件事。但是它们存在。函数式语言具有许多最佳实践规则,其形式为“遇到问题X时,使用看起来像Y的代码”,这基本上就是一种设计模式。
但是,正确的是,大多数特定于OOP的设计模式在功能语言中几乎无关紧要。
我认为一般地说设计模式只是为了弥补该语言的缺点而引起的争议并不特别有争议。而且,如果另一种语言可以轻松解决相同的问题,那么该另一种语言将不需要设计模式。使用该语言的用户甚至可能没有意识到问题的存在,因为,这不是该语言的问题。
这是“四人帮”对此问题的评价:
编程语言的选择很重要,因为它会影响一个人的观点。我们的模式假定使用Smalltalk / C ++级别的语言功能,并且该选择确定了可以轻松实现的内容。如果我们采用过程语言,则可能包括称为“继承”,“封装”和“多态”的设计模式。同样,不太常见的面向对象语言直接支持我们的某些模式。例如,CLOS具有多种方法,可以减少对访问者之类的模式的需求。实际上,Smalltalk和C ++之间存在足够的差异,这意味着某些模式可以用一种语言比另一种语言更容易地表达。(例如,请参见Iterator。)
(以上引自《设计模式简介》第4页第3段)
函数式编程的主要功能包括一流的值,currying,不可变的值等功能。对于我来说,OO设计模式几乎可以近似所有这些功能。
命令模式是什么(如果不是一流函数的近似)?:)在FP语言中,您只需将一个函数作为参数传递给另一个函数。在OOP语言中,必须将函数包装在一个类中,可以实例化该类,然后将该对象传递给另一个函数。效果是相同的,但是在OOP中,它称为设计模式,并且需要大量的代码。如果不使用抽象工厂模式,那又是什么呢?一次将参数传递给一个函数,以配置在最终调用它时会吐出的值。
因此,是的,由于存在更强大且更易于使用的替代方案,因此几种GoF设计模式在FP语言中变得多余。
但是,当然,仍然有设计这些图案不是通过FP语言解决。FP等于单身人士吗?(暂时忽略单例通常是一个可怕的模式。)
而且它也双向起作用。如我所说,FP也有其设计模式。人们通常通常不会这样认为。
但是您可能遇到过单子。如果不是“应对全球状态”的设计模式,它们是什么?这个问题在OOP语言中是如此简单,以至于那里没有等效的设计模式。
我们不需要一个设计模式为“增加一个静态变量”,或“从套接字读取”,因为它是你正是这样做。
说单子是一种设计模式,就像说整数以其通常的操作和零元素是一种设计模式一样荒谬。不,monad是数学模式,而不是设计模式。
在(纯)功能语言中,除非您使用monad“设计模式”或允许同一事物的任何其他方法来解决,否则副作用和可变状态是不可能的。
此外,在支持OOP的功能语言(例如F#和OCaml)中,对我来说显而易见的是,使用这些语言的程序员将使用与其他OOP语言相同的设计模式。实际上,现在我每天都使用F#和OCaml,并且在这些语言中使用的模式与用Java编写时使用的模式之间没有显着差异。
也许是因为您仍在进行必要的思考?许多人一生都在使用命令式语言,但是在尝试使用功能性语言时却很难放弃这种习惯。(我在F#上看到了一些非常有趣的尝试,实际上每个函数只是一串'let'语句,基本上就像您使用了C程序一样,并用'let'替换了所有分号。:)
但是另一种可能是,您可能还没有意识到自己正在琐碎地解决问题,而这需要使用OOP语言的设计模式。
当您使用currying或将一个函数作为参数传递给另一个函数时,请停下来想一想如何使用OOP语言来实现。
函数式编程消除了对OOP设计模式的需求,这有何道理?
是的 :)使用FP语言时,您不再需要特定于OOP的设计模式。但是,您仍然需要一些通用的设计模式,例如MVC或其他非OOP特定的内容,并且需要几个新的FP特定的“设计模式”。所有语言都有其缺点,设计模式通常是我们解决它们的方法。
无论如何,您可能会发现尝试使用“更清洁”的FP语言很有趣,例如ML(我个人最喜欢的,至少出于学习目的)或Haskell,而您没有OOP拐杖可以依靠面临着新的事物。
不出所料,一些人反对我对设计模式的定义为“弥补一种语言的缺点”,所以这是我的理由:
如前所述,大多数设计模式特定于一种编程范例,有时甚至特定于一种特定的语言。通常,它们可以解决仅存在于该范式中的问题(有关FP,请参见monad;有关OOP,请参见抽象工厂)。
为什么FP中不存在抽象工厂模式?因为它尝试解决的问题在那里不存在。
因此,如果OOP语言中存在问题,而FP语言中不存在问题,那么显然这是OOP语言的缺点。该问题可以解决,但是您的语言却不能解决,但是您需要一堆样板代码来解决。理想情况下,我们希望我们的编程语言能够神奇地解决所有问题。原则上仍然存在任何问题,这是该语言的缺点。;)