前言:
以下内容来源于java8实战一书,我将里面学习的内容做一个整理,方便忙碌的小伙伴快速入门实战java8
正文:
假设一个果农收获了一园的苹果,他需要你根据他的条件筛选出满意的苹果
首先我们新建一个Apple类
public class Apple { /** * 重量 */ private Integer weight; /** * 颜色 */ private String color;
getter();
setter();
toString();
... }
他说:我需要挑出红苹果
public void filterRedApple(List<Apple> appleList){ for(Apple apple : appleList){ if("red".equals(apple)){ System.out.println("红苹果"); } } }
他说:我要挑出绿苹果
转念一想,把颜色作为参数吧
public void filterGreenApple(List<Apple> appleList , String color) { for (Apple apple : appleList) { if (color.equals(apple)) { System.out.println("绿苹果"); } } }
他说:我需要挑出150g的苹果
public void filterWeightApple(List<Apple> appleList,Integer weight) { for (Apple apple : appleList) { if (apple.getWeight() > weight) { System.out.println("重量大于150g的苹果"); } } }
他说:我要挑出100g以上的红苹果
public void filterAppleByWeightAndColor(List<Apple> appleList,String color,Integer weight){ for (Apple apple : appleList) { if (apple.getWeight() > weight && color.equals(apple.getColor())) { System.out.println("重量大于100g的红苹果"); } } }
面对无止境的需求变化,我们需要不断的适应
让我们来看看如何改进
新建一个苹果筛选接口
public interface ApplePredicate { /** * 筛选苹果 */ boolean test(Apple apple); }
然后我们分别实现筛选方法
根据颜色筛选
public class FilterRedApple implements ApplePredicate { @Override public boolean test(Apple apple) { return "red".equals(apple.getColor()) ? true : false; } }
根据重量筛选
public class FilterWeightApple implements ApplePredicate { @Override public boolean test(Apple apple) { return apple.getColor() > 100 ? true : false; } }
根据颜色和重量筛选
public class FilterAppleByColorAndWeight implements ApplePredicate { @Override public boolean test(Apple apple) { return "red".equals(apple.getColor()) && apple.getWeight > 100 ? true : false; } }
比如他想要红苹果
我们这样来给他实现
public static void filterApple(List<Apple> appleList , ApplePredicate p) { for (Apple apple : appleList) { if (p.test(apple)) { System.out.println("这是你要的苹果" + apple.toString()); } } }
我们调用的时候,传入它的实现类就行了
public static void main(String[] args) { filterApple(appleList, new FilterRedApple()); filterApple(appleList, new FilterWeightApple()); }
我们来看看现在的方法和原先的方法的区别:
原先的方法是每提出一个需求我们就新写一个方法来实现它,这样代码会显得非常臃肿冗余,因为他们其实是做的同一件事:筛选想要的苹果,仅仅只是条件不同
我们改进后的方法是:写一个筛选接口,然后分别实现这个接口,比如你想要红苹果就写个晒选红苹果的实现,想要大的苹果就再写一个新的实现
这看起来有点像策略模式
好的。我们已经完成了一件非常酷的事:fliterApple方法的行为取决于我们通过ApplePredicate对象传递的代码,这个就是行为参数化,它可以帮助我们编写灵活的API
现在,可能有同学会问我,每次新的需求都写一个新的实现类,会不会太麻烦了,我们可以用匿名类来实现啊
确实,我们可以用匿名类来实现
public static void main(String[] args) {
filterApple(appleList, new ApplePredicate() {
@Override public boolean test(Apple apple) { return "red".equal(apple.getColor) ? true : false; } });
}
虽然匿名类在一定程度上改善了为一个接口写好几个实现类的啰嗦问题,但它还是要创建一个对象明确的实现新的方法来定义一个新的行为
所以,相较之下我更倾向于使用行为参数化的形式
概念:
行为参数化:一个方法接受多个不同的行为作为参数,并在内部使用他们,完成不同行为的能力
行为参数化可以让代码更好的适应不断变化的需求,减轻未来的工作量
传递代码:将新行为作为参数传递给方法