第一章:行为参数化
1.1 应对不断变化的需求:
有一个 Apple 实体类:
public class Apple { private int weight = 0; private String color = ""; public Apple(int weight, String color){ this.weight = weight; this.color = color; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String toString() { return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}'; } }
构造测试数据:
public static List<Apple> inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"));
1.1.1 初试牛刀:筛选绿苹果
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; }
如果需求变了,想让你筛选出红苹果,你可以将其copy一下改为filterRedApples方法。可是如果要你筛选更多种颜色的苹果,你会考虑将其抽象化。
1.1.2 再显身手:将颜色作为参数
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){ List<Apple> result = new ArrayList<>(); for(Apple apple: inventory){ if(apple.getColor().equals(color)){ result.add(apple); } } return result; }
如果需求说要你筛选出不同重量的苹果:
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; }
1.1.3 第三次尝试:对你能想到的每一个属性进行筛选
public static List<Apple> filterApples(List<Apple> inventory, String color, int weight)
1.2 行为参数化:
定义一个接口来对选择标准建模:
interface ApplePredicate{ public boolean test(Apple a); }
现在你就可以使用不同的实现来代表不同的选择标准了:
static class AppleWeightPredicate implements ApplePredicate{ public boolean test(Apple apple){ return apple.getWeight() > 150; } } static class AppleColorPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "green".equals(apple.getColor()); } } static class AppleRedAndHeavyPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "red".equals(apple.getColor()) && apple.getWeight() > 150; } }
第四次尝试:根据抽象条件筛选
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate<Apple> p){ List<Apple> result = new ArrayList<>(); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); } } return result; }
传递代码/行为:
static class AppleRedAndHeavyPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "red".equals(apple.getColor()) && apple.getWeight() > 150; } } List<Apple> redAndHeavyApples = filterApples(inventory, new AppleRedAndHeavyPredicate());
1.3 对付啰嗦:
目前,当把把新的行为传入filterApples方法的时候,你不得不声明好几个实现ApplePredicate的接口的实现类,然后实例化只会用的一次的ApplePredicate对象
1.3.1 匿名类,第五次尝试:使用匿名类
List<Apple> redApples2 = filterApples(inventory, new ApplePredicate() {
public boolean test(Apple a){ return a.getColor().equals("red"); } });
1.3.2 第六次尝试:使用Lambda表达式
List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
1.3.3 第七次尝试:将List类型抽象化
filterApples方法只适用于Apple,你可以将List类型抽象化
interface Predicate<T>{ public boolean test(T t); } public static <T> List<T> filter(List<T> list, Predicate<T> p){ List<T> result = new ArrayList<>(); for(T e: list){ if(p.test(e)){ result.add(e); } } return result; }
这样你家就可以将filter方法应用在苹果,香蕉,Integer或String等各个类型上了
List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
List<Integer> evenNumber = filter(numbers, (Integer i) -> i % 2 == 0);
1.4 真实的例子
现在你已经看到了,行为参数化是一个很有用的模式,它可以轻松应对不断变化的需求。这种模式可以把一个行为(一段代码)封装起来,并通过传递和使用创建的行为将方法的行为参数化,这种做法类似于策略设计模式(定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换)。下面看几个例子:
1.4.1 用Comparator来排序:
在java8中,List自带了一个sort的方法(你可以直接使用Collections.sort)。sort的行为可以用java.util.Comparator对象来参数化,它的方法如下:
public interface Comparator<T> { int compare(T o1, T o2); ... }
因此你可创建不同的实现用sort方法表现出不同的排序行为,比如使用匿名内部类按照重量升序排列:
inventory.sort(new Comparator<Apple>(){ public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); } })
使用Lambda表达式:
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
1.4.2 用Runnable执行代码块:
创建线程:
Thread t = new Thread(new Runnable() { public void run() { System.out.println("Hello World"); } });
使用Lambda表达式:
Thread t = new Thread(() -> System.out.println("Hello World"));
备注:
摘自文献:《Java8实战》(中文版)《Java8 in Action》(英文版)
代码(GitHub地址): git@github.com:changlezhong/java8InAction.git
posted on 2018-06-02 23:22 changlezhong 阅读(656) 评论(0) 编辑 收藏 举报