什么是行为参数化?

一个方法接收多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。

有什么好处?

让代码更好的适应不断变化的要求,对付啰嗦,减轻未来的变化量。

问题

对苹果按要求进行筛选,比如:重量、颜色等(*需求是变化的哦*)

Apple类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class Apple {
    private int weight;
    private String color;

    public Apple(int weight, String color){
        this.weight = weight;
        this.color = color;
    }
    
	// getter and setter
	
    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }
}

Bad code

筛选方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//按颜色筛选,传递颜色参数
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; 
}

Better code

上述代码存在问题:无法应对需求变化,比如:按重量和颜色筛选、按重量或颜色筛选等。

筛选接口
1
2
3
4
//行为参数化
public interface ApplePredicate {
    boolean test(Apple a);
}
筛选实现类
  • 按颜色筛选

    1
    2
    3
    4
    5
    6
    
    public class AppleGreenColorPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple a) {
        return "green".equals(a.getColor());
    }
    }
  • 按重量筛选

    1
    2
    3
    4
    5
    6
    
    public class AppleHeavyWeightPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple a) {
        return a.getWeight() > 150;
    }
    }
筛选方法
1
2
3
4
5
6
7
8
9
public static List<Apple> filterApples(List<Apple> invertory, ApplePredicate predicate) {
        List<Apple> result = new ArrayList<>();
        for(Apple apple : invertory){
            if (predicate.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }
方法使用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public static void main(String[] args) {
    List<Apple> inventory = Arrays.asList(
            new Apple(80, "green"),
            new Apple(155, "green"),
            new Apple(120, "red"));
    List<Apple> heavyApples = filterApples(inventory,
            new AppleHeavyWeightPredicate());
    List<Apple> greenApples = filterApples(inventory,
            new AppleGreenColorPredicate());
}

重构-改进(More better)

对筛选接口和筛选方法抽象化(使用泛型),可接受任何类型的参数。

筛选接口
1
2
3
public interface ApplePredicate<T> {
    boolean test(T t);
}
筛选方法
1
2
3
4
5
6
7
8
9
public static <T> List<T> filter(List<T> list, ApplePredicate<T> predicate){
        List<T> result = new ArrayList<>();
        for (T t : list) {
            if (predicate.test(t)){
                result.add(t);
            }
        }
        return result;
    }
方法使用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
	List<Apple> inventory = Arrays.asList(
        new Apple(80, "green"),
        new Apple(155, "green"), 
        new Apple(120, "red"));
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
    // 筛选苹果
    List<Apple> heavyApples = filterApples(inventory,
            new AppleHeavyWeightPredicate());
    // 筛选数字 
    filter(numbers, new ApplePredicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer > 3;
            }
        });
    }
}

Good code

上述代码看上去已经不错了,但是每个算法(筛选类型)都要实现一个只有几行代码的具体类,比较啰嗦。more better?使用Lambda表达式实现行为算法。

1
2
3
4
5
6
// 筛选红苹果
List<Apple> redApples = filter(inventory, 
            apple -> "red".equals(apple.getColor())); 
//筛选偶数
List<Integer> evenNumbers = filter(numbers, 
            integer -> integer % 2 == 0);

One more Thing

  • 用Comparator排序

    1
    2
    3
    4
    5
    6
    7
    8
    
    List<Apple> inventory = Arrays.asList(
                new Apple(80, "green"),
                new Apple(155, "green"),
                new Apple(120, "red"));
    //按重量排序
    inventory.sort((Apple apple1, Apple apple2) -> apple1.getWeight()- apple2.getWeight());
    // 按颜色排序
    inventory.sort((a1, a2) -s> a1.getColor().compareTo(a2.getColor()));
  • 用Runable执行代码块

    1
    2
    
    Thread thread = new Thread(() -> System.out.println("hello"));
    thread.start();