什么是行为参数化?
一个方法接收多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。
有什么好处?
让代码更好的适应不断变化的要求,对付啰嗦,减轻未来的变化量。
问题
对苹果按要求进行筛选,比如:重量、颜色等(*需求是变化的哦*)
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();
|