从上一讲开始,我们开启了函数式编程之旅,相信你已经对函数式编程有了一个初步的认识。函数式编程是一种以函数为编程元素的编程范式。但是,如果只有函数这一样东西,即使是说出花来,也没有什么特别的地方。
之前我讲过,GC 来自于函数式编程,Lambda 也来自于函数式编程。此外,在 Java 8 增加的对函数式编程的处理中,流(Stream)的概念也从函数式编程中来,Optional 也和函数式编程中的一些概念有着紧密的联系。由此可见,函数式编程给我们提供了许多优秀的内容。
接下来,我们来讲讲函数式编程在设计上对我们帮助最大的两个特性:组合性和不变性。
首先,我们来讨论一下组合性,看看函数式编程为什么能够如此吸引人。
组合行为的高阶函数
在函数式编程中,有一类比较特殊的函数,它们可以接收函数作为输入,或者返回一个函数作为输出。这种函数叫做高阶函数(High-order function)。
听上去稍微有点复杂,如果我们回想一下高中数学里有一个复合函数的概念,也就是 f(g(x)) ,把一个函数和另一个函数组合起来,这么一类比,是不是就好接受一点了。
那么,高阶函数有什么用呢?它的一个重要作用在于,我们可以用它去做行为的组合。我们再来回顾一下上一讲写过的一段代码:
find(byName(name).and(bySno(sno)));
在这里面,find 的方法就扮演了一个高阶函数的角色。它接收了一个函数作为参数,由此,一些处理逻辑就可以外置出去。这段代码的使用者,就可以按照自己的需要任意组合。
你可能注意到了,这里的 find 方法只是一个普通的 Java 函数。是这样的,如果不需要把这个函数传来传去,普通的 Java 函数也可以扮演高阶函数的角色。
可以这么说,高阶函数的出现,让程序的编写方式出现了质变。按照传统的方式,程序库的提供者要提供一个又一个的完整功能,就像 findByNameAndBySno 这样,但按照函数式编程的理念,提供者提供的就变成了一个又一个的构造块,像 find、byName、bySno 这样。然后,使用者可以根据自己的需要进行组合,非常灵活,甚至可以创造出我们未曾想过的组合方式。
这就是典型的函数式编程风格。模型提供者提供出来的是一个又一个的构造块,以及它们的组合方式。由使用者根据自己需要将这些构造块组合起来,提供出新的模型,供其他开发者使用。就这样,模型之间一层又一层地逐步