行为参数化

本篇内容摘自《Java8 实战》

前言

行为参数化和“策略设计模式”相关,它让你定义算法,并将其封装起来(这里称为“策略”),在运行的时候选择一个算法,如果你现在不太明白这句话的意思,可以紧张兮兮的往下看,我将会通过一系列的例子来展示什么叫做行为参数化,以及这种设计模式的优点。

需求

0、准备

我们先准备一个苹果的实体类,重写它的toString()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Apple {

/**
* 苹果颜色
*/
private String color;

/**
* 苹果重量(单位:克)
*/
private Integer weight;

public Apple(String color, Integer weight) {
this.color = color;
this.weight = weight;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public Integer getWeight() {
return weight;
}

public void setWeight(Integer weight) {
this.weight = weight;
}

@Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}

然后准备一个工具类去生成测试代码所需的苹果的集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AppleUtil {
public static List<Apple> getApples() {
return Arrays.asList(
new Apple("green", 100),
new Apple("green", 120),
new Apple("red", 130),
new Apple("green", 140),
new Apple("red", 150),
new Apple("green", 160),
new Apple("green", 170),
new Apple("red", 180),
new Apple("green", 190),
new Apple("red", 200),
new Apple("green", 210)
);
}
}

至此,准备工作完成。

1、筛选绿苹果

首先,我们需要从一堆苹果中筛选出绿色的苹果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo1 {
public static void main(String[] args) {
List<Apple> apples = filterGreenApples(AppleUtil.getApples());
for (Apple apple : apples) {
System.out.println(apple);
}
}
/**
* 获取绿色的苹果
* @param inventory 未筛选的苹果集合
* @return 绿色苹果的集合
*/
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;
}
}

这很简单,我们定义了一个filterGreenApples方法,参数为List<Apple>,然后在方法体内遍历这个List,如果苹果是绿色的,就把这个苹果放到新的List<Apple>中,遍历完成后返回新的List<Apple>

2、筛选红苹果

有了筛选绿苹果的经历 ,我们微微一笑,将之前封装的filterGreenApples复制一份,然后改名为filterRedApples,然后修改if代码块中的代码修改为"red".equals(apple.getColor()),其完整代码如下

1
2
3
4
5
6
7
8
9
public static List<Apple> filterRedApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ("red".equals(apple.getColor())) {
result.add(apple);
}
}
return result;
}

看上去我们“完美”的完成了任务,准备提交代码的时候,又来了一个需求,筛选一半红一半绿的苹果,这时候我们就不太想复制之前的代码了,何不将颜色作为参数传入方法中呢,说干就干

1
2
3
4
5
6
7
8
9
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的苹果,我要筛选出出重量大于150g的红苹果,那我们现有的架构也没法实现这个需求,而且封装的方法会越来越庞大,我们下面将介绍如何去解决这些我呢提。

3、代码重构

首先我们写一个接口ApplePredicate

1
2
3
4
5
@FunctionalInterface
public interface ApplePredicate {

boolean test(Apple apple);
}

我们先不管这个注解,然后再写两个实现类,AppleGreenColorPredicateAppleHeavyWeightPredicate

1
2
3
4
5
6
public class AppleGreenColorPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return "green".equals(apple.getColor());
}
}
1
2
3
4
5
6
public class AppleHeavyWeightPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}

然后我们可以封装这样一个方法

1
2
3
4
5
6
7
8
9
public static List<Apple> filterApplesByPredicate(List<Apple> inventory, ApplePredicate predicate) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (predicate.test(apple)) {
result.add(apple);
}
}
return result;
}

测试代码

1
2
3
4
5
6
7
public static void main(String[] args) {

List<Apple> apples = filterApplesByPredicate(AppleUtil.getApples(), new AppleGreenColorPredicate());
for (Apple apple : apples) {
System.out.println(apple);
}
}

具体的代码逻辑直接在ApplePredicate的实现类中实现就可以了,将具体的行为当作参数传入到方法中,这就是行为参数化。

# Java
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×