Java8之通过行为参数化传递代码
在软件工程中,一个众所周知的问题就是,不管你做什么,用户的需求肯定会变.比方说,有个应用程序是帮助农民了解自己的库存.这位农民可能想有一个查找库存中所有绿色苹果的功能.但到了第二天,他可能会告诉你,还想要一个查找重量超过150g的苹果,但又过了几天,他又跑回来补充道,想找出所有绿色,重量也超过150g 的苹果…
行为参数化
行为参数化,就是可以帮助我们处理频繁变化需求的一种软件开发模式,通俗的说,就是拿出一个代码块,把它准备好,却不去执行它。这个代码块以后可以被程序的其他部分调用,这就意味着我们可以推迟这块代码的执行。例如,你可以将代码块作为参数传递给另一个方法,稍后再去执行它,这样,这个方法的行为就基于那块代码被参数化了.
第一次尝试
筛选出来所有颜色是绿色的苹果,遍历一下把绿色苹果放到新的集合
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ("green".equals(apple.getColor())) {
result.add(apple);
}
}
return result;
}
第二次尝试
实现一个筛选红色苹果的接口,把color抽象出来,变成一个参数传进来,这样你要什么颜色的我都有了。
public static 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;
}
第三次尝试
区分,大苹果和小苹果,大苹果是重量大于150g的。
public static 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;
}
第四次尝试
过滤那些绿色的且重量大于150g的苹果。
public static List<Apple> filterApples(List<Apple> inventory, String color, int weight,boolean flag) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ((flag &&apple.getColor().equals(color)) ||(!flag &&apple.getWeight().>weight)) {
result.add(apple);
}
}
return result;
}
List<apple> greenAlpples = filterApples(inventory,"green",0,true);
List<apple> heavyAlpples = filterApples(inventory," ",150,false);
第五次尝试
策略模式,通过一个接口来实现传递不同的参数.
public interface ApplePredicate {
boolean test(Apple apple);
}
//绿色苹果
public class AppleGreenPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return apple.getColor().equals("green");
}
}
//大苹果
public class AppleHeavyWeightPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}
//代码主体
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
第六次尝试
缺点:每次一个新的逻辑都要去实现这个接口,匿名类优化
List<Apple> greenApples = filterApples(inventory, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return apple.getColor().equals("green");
}
});
通过lambda表达式来传递核心代码,
List<Apple> result = filterApples(inventory, (Apple apple) -> apple.getColor().equals("green"));
可以把类型去掉
List<Apple> result = filterApples(inventory, apple -> apple.getColor().equals("green"));