java8新特性之行为参数化
为什么要有行为参数化?
在软件工程中,一个众所周知的问题就是,不管你做什么,用户的需求肯定会变。。比方说,有个应用程序是帮助农民了解自己的库存的。这位农民可能想有一个查找库存中所有绿色苹果的功能。但到了第二天,他可能会告诉你:“其实我还想找出所有重量超过150克的苹果。”又过了两天,农民又跑回来补充道:“要是我可以找出所有既是绿色,重量也超过150克的苹果,那就太棒了。”你要如何应对这样不断变化的需求?理想的状态下,应该把你的工作量降到最少。此外,类似的新功能实现起来还应该很简单,而且易于长期维护。
什么是行为参数化
行为参数化就是可以帮助你处理频繁变更的需求的一种软件开发模式。一言以蔽之,它意味着拿出一个代码块,把它准备好却不去执行它。这个代码块以后可以被你程序的其他部分调用,这意味着你可以推迟这块代码的执行。
。例如,如果你要处理一个集合,
可能会写一个方法:
可以对列表中的每个元素做“某件事”
可以在列表处理完后做“另一件事”
遇到错误时可以做“另外一件事”
它可以接受不同的新行为作为参数,然后去执行。
需求复杂变化
随着需要变化越来越多. 参数列表会越来越长. 必须如果要在加上重量的判断.就会变成如下类型.
参数列表长, 且不容易理解.
让行为参数化
我们可以定义一个接口,然后创建不用的实现类(有点策略模式的感觉)
需要什么行为,就创建对应的接口实现类.
效果是这样的.
List<Apple> redAndHeavyApples = filterApples(inventory, new AppleRedAndHeavyPredicate());
你已经做成了一件很酷的事:filterApples方法的行为取决于你通过ApplePredicate对象传递的代码。换句话说,你把filterApples方法的行为参数化了!
多种行为,一个参数
这就是说行为参数化是一个有用的概念的原因。你应该把它放进你的工具箱里,用来编写灵活的API。
测试
测验2.1:编写灵活的prettyPrintApple方法
编写一个prettyPrintApple方法,它接受一个Apple的List,并可以对它参数化,以多种方式根据苹果生成一个String输出(有点儿像多个可定制的toString方法)。例如,你可以告诉 prettyPrintApple 方法,只打印每个苹果的重量。此外,你可以让prettyPrintApple方法分别打印每个苹果,然后说明它是重的还是轻的。解决方案和我们前面讨论的筛选的例子类似。为了帮你上手,我们提供了prettyPrintApple方法的一个粗略的框架:
答案如下:
首先,你需要一种表示接受Apple并返回一个格式String值的方法。前面我们在编写
ApplePredicate接口的时候,写过类似的东西:
public interface AppleFormatter{
String accept(Apple a);
}
现在你就可以通过实现AppleFormatter方法,来表示多种格式行为了:
对付啰嗦
当要把新的行为传递给
filterApples方法的时候,你不得不声明好几个实现ApplePredicate接口的类,然后实例化好几个只会提到一次的ApplePredicate对象。。这真是很啰嗦,很费时间!
解决啰嗦1(不太完美)
使用匿名类:
匿名类和你熟悉的Java局部类(块中定义的类)差不多,但匿名类没有名字。它允许你同时
声明并实例化一个类。换句话说,它允许你随用随建。
解决啰嗦2(太完美)
使用 Lambda 表达式:
小结
行为参数化,就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。
行为参数化可让代码更好地适应不断变化的要求,减轻未来的工作量。
传递代码,就是将新行为作为参数传递给方法。但在Java 8之前这实现起来很啰嗦。为接声明许多只用一次的实体类而造成的啰嗦代码,在Java 8之前可以用匿名类来减少。
Java API包含很多可以用不同行为进行参数化的方法,包括排序、线程和GUI处理。