【Java 8】行为参数化
来源:互联网 发布:ug编程二次开粗技巧 编辑:程序博客网 时间:2024/05/20 07:37
【Java 8】行为参数化
行为参数化——Lambda表达式之前
行为参数化,就是可以帮助你处理频繁变更的需求的一种软件开发模式。
行为参数化,旨在抽象出具有某种功能的代码(它的输入参数和返回值是固定的),以某种方式将此代码传入到其他的方法中,以辅助它们的操作。
行为参数化之前
应对不断变化的需求的一个例子——选苹果
其中,苹果的定义如下:
private class Apple{ private int weight; private String color; // constructor, setter, getter }
需求一:挑选出集合中的青苹果或者红苹果
我们可以非常容易的想到下面的方法,在挑选的方法参数列表中加上color条件,
遍历集合,如果当前苹果的颜色跟指定颜色相等,则加入到表示结果的集合中。
方案:
public List<Apple> filterApplesByColor(List<Apple> inventory, String color){ List<Apple> result = new ArrayList<>(); for (Apple apple : inventory){ if (color.equals(apple.getColor())) result.add(apple); } return result; }
需求二:挑选出集合中重量大于200的苹果
和需求一的解决方案类似,在挑选的方法参数列表中加上weight参数,
遍历集合,如果当前苹果的重量大于weight,则加入到表示结果的集合中。
public List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){ List<Apple> result = new ArrayList<>(); for (Apple apple : inventory){ if (apple.getWeight() > weight) result.add(apple); } return result; }
……
需求N:挑选重量在100~200之间的红色苹果。
此时,如果按照上面的方法,需要不断地实现挑选苹果的方法。
怎么简化开发呢?其实,上面的方法各不相同,但是他们有一个共同点,就是选择苹果时,需要一个标准,满足这个标准则挑选出来,否则,跳过。很明显,这个标准可以定义为只有两种返回值的布尔类型的方法。如果能够定义这样的标准,并把它们传递给挑选方法,我们通过一个挑选方法就可以挑选满足各种条件的苹果。
那么,怎么实现这个想法呢?
答案是,通过对象传递方法。
行为参数化
我们先定义一个接口,这个接口只有一个抽象方法,传递给它一个苹果,它返回boolean类型的结果。
当前不需要关心这个抽象方法的方法体的具体判断内容是什么。首要任务是,能把这个方法传递给挑选苹果的方法中。
interface ApplePredicate{ public boolean test(Apple apple); }
此时,我们在挑选苹果的方法中调用这个挑选条件
public List<Apple> filterApplesByPredicate(List<Apple> inventory, ApplePredicate predicate){ List<Apple> result = new ArrayList<>(); for (Apple apple : inventory){ if (predicate.test(apple)) result.add(apple); } return result; }
predicate.test(apple) 成功地嵌入到挑选苹果的方法中了
以后,我们再挑选苹果,只需要把实现ApplePredicate接口,覆写predicate.test(apple)方法,把实现类的实例传递给挑选苹果的方法就可以选择满足条件的苹果,我们不需要多次写挑选苹果的代码。
比如,我们要挑选出青苹果,首先实现覆写test方法,然后将接口的实例传递给挑选苹果的方法即可。
class AppleColorPredicate implements ApplePredicate{ @Override public boolean test(Apple apple) { return "green".equals(apple.getColor()); } } List<Apple> result = filterApplesByPredicate(appleList, new AppleColorPredicate());
同样,我们以可以选择重量在160一下的苹果
class AppleWeightPredicate implements ApplePredicate{ @Override public boolean test(Apple apple) { return apple.getWeight() < 160; } }List<Apple> result = filterApplesByPredicate(appleList, new AppleWeightPredicate())
至此,我们以可以不用重复编写挑选苹果的方法,只需要覆写挑选条件方法即可,这比行为参数化之间简化了代码量。
但是,这也有一个很大的弊端,随着挑选条件的变化,我们需要不停地创建新的实现了指定接口的类。
一个好主意是,使用匿名类。
比如,挑选出重量小于200的绿苹果。
public void filterApplesByAnonymousPredicate(){ List<Apple> result = filterApplesByPredicate(appleList, new ApplePredicate(){ @Override public boolean test(Apple apple) { return "green".equals(apple.getColor()) && apple.getWeight() < 200; } }); }
以上,行为参数化的本质,是通过传递对象实现传递方法(方法属于某个对象)。
不停地实现这个指定的接口并不能使人满意,代码还可以再简化吗?
在Java8之前,没有什么更好的办法了。
好在,Java8为我们提供了更加简便、更加优雅的实现方式——Lambda表达式。
初探Lambda表达式
如果和行为参数中一样,我们定义了只含有一个抽象方法的接口和挑选苹果的方法,如下:
interface ApplePredicate{ public boolean test(Apple apple);}public List<Apple> filterApplesByPredicate(List<Apple> inventory, ApplePredicate predicate){ List<Apple> result = new ArrayList<>(); for (Apple apple : inventory){ if (predicate.test(apple)) result.add(apple); } return result;}
使用Lambda表达式挑选红苹果和挑选出重量小于160的苹果的代码如下:
List<Apple> result = filterApplesByPredicate(appleList, (Apple apple) -> "red".equals(apple.getColor())); ApplePredicate weigthPredicate = (Apple apple) -> apple.getWeight() < 160; List<Apple> result02 = filterApplesByPredicate(appleList, weigthPredicate);
此时,代码变得如此简洁,让人觉得不可思议。
Java8,good job。
不过,初次见面,为何觉得Lambda表达式如此奇怪?下一节,将详细介绍Lambda表达式。
参考:《Java 8 in action》
- 【Java 8】行为参数化
- Java 8 之 行为参数化
- Java 8 实战学习——行为参数化
- Java8-行为参数化
- 【Java8】 行为化参数
- 读书笔记——《Java 8实战》系列之行为参数化
- 从JAVA行为参数化到 JAVA8 lamada,方法引用
- 值参数化和行为参数化
- 《Java in Action》-1 第2章 通过行为参数化传递代码
- JAVA8实战 第二章行为参数化
- Java8学习笔记之行为参数化
- java8之行为参数化(一)
- java8之行为参数化(二)
- Java_通过行为参数化传递代码
- C# 参数传递行为
- java8之行为参数化(函数为值化)
- java8新特性(一):行为参数化
- Java8函数式编程之一: 行为参数化
- BZOJ 1014 火星人 prefix (splay hash 二分答案)
- python数据分析师面试题选
- Android中Parcelable接口用法
- 数据分析师是青春饭吗,前景如何?
- tabControl添加Form作为tabPage的控件,切换时不显示form的问题
- 【Java 8】行为参数化
- HDU 1847 Good Luck in CET-4 Everybody!(SG)
- 要想富先练功,设计模式之六大原则
- 为什么要引入数据库缓存,如redis?
- 使用两个栈实现一个队列+使用两个队列实现一个栈
- Java集合小结
- 『毒舌电影社区』干掉烂片,让烂片无路可走!
- CodePush配置
- tbschedule与spring整合