flea-common使用之通用策略模式实现

1. 概述

策略模式(Strategy Pattern)作为一种软件设计模式,用来实现对象的某个行为,该行为在不同的场景中拥有不同的实现逻辑。它定义了一组算法,同时将这些算法封装起来,并使它们之间可以互换。

常用的策略模式有如下三个角色:

  • 抽象策略角色 — Strategy
    抽象策略类,通常为一个接口,其中定义了某个策略行为【即策略算法标识】。

  • 具体策略角色 — ConcreteStrategy
    具体策略类,实现抽象策略中的策略行为;每一个具体策略类即代表一种策略算法。

  • 上下文角色 — Context
    上下文类,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

本篇在上述常用的策略模式基础上,结合门面模式和调整后的策略上下文,构建了一套通用策略模式实现。

下面我们用这套通用策略模式来模拟一下各种动物的喊叫行为:

2. 参考

flea-common使用之通用策略模式实现 源代码

3. 实现

3.1 定义Flea策略接口类

IFleaStrategy 定义了通用的策略行为,T 类型表示 Flea 策略执行结果对应的类型,P 类型表示 Flea 策略上下文参数。 具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Flea策略接口,定义统一的策略执行方法。
*
* @param <T> Flea策略执行结果对应的类型
* @param <P> Flea策略上下文参数
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public interface IFleaStrategy<T, P> {

/**
* 策略执行
*
* @param contextParam Flea策略上下文参数
* @return 策略执行结果对应的类型
* @throws FleaStrategyException Flea策略异常
* @since 1.1.0
*/
T execute(final P contextParam) throws FleaStrategyException;
}

3.2 定义狗喊叫声策略类

DogVoiceStrategy 用于定义狗喊叫声策略,返回 "阿狗【" + name + "】正在喊叫着;汪汪汪"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 狗喊叫声策略
*
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class DogVoiceStrategy implements IFleaStrategy<String, String> {

@Override
public String execute(String name) throws FleaStrategyException {
return "阿狗【" + name + "】正在喊叫着;汪汪汪";
}

}

3.3 定义猫喊叫声策略类

CatVoiceStrategy 用于定义猫喊叫声策略,返回 "阿猫【" + name + "】正在喊叫着;喵喵喵"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 猫喊叫声策略
*
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class CatVoiceStrategy implements IFleaStrategy<String, String> {

@Override
public String execute(String name) throws FleaStrategyException {
return "阿猫【" + name + "】正在喊叫着;喵喵喵";
}

}

3.4 定义鸭喊叫声策略类

DuckVoiceStrategy 定义鸭喊叫声策略,返回 "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 鸭喊叫声策略
*
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class DuckVoiceStrategy implements IFleaStrategy<String, String> {

@Override
public String execute(String name) throws FleaStrategyException {
return "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎";
}

}

3.5 定义策略上下文接口类

IFleaStrategyContext 策略上下文接口,定义统一的策略上下文调用方法,同时可通过 getContext 获取上下文参数,setContext 设置上下文参数。

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
/**
* Flea策略上下文接口,定义统一的策略上下文调用方法。
*
* @param <T> Flea策略执行结果对应的类型
* @param <P> Flea策略上下文参数
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public interface IFleaStrategyContext<T, P> {

/**
* 策略上下文调用
*
* @param strategy 策略名称
* @return 策略执行结果对应的类型
* @throws FleaStrategyException Flea策略异常
* @since 1.1.0
*/
T invoke(String strategy) throws FleaStrategyException;

/**
* 设置策略上下文参数
*
* @param contextParam 上下文参数对象
* @since 1.1.0
*/
void setContext(P contextParam);

/**
* 获取策略上下文参数
*
* @return 策略上下文参数
* @since 1.1.0
*/
P getContext();
}

3.6 定义Flea抽象策略上下文类

FleaStrategyContext Flea 抽象策略上下文类,封装了策略执行的逻辑,对外屏蔽高层模块对策略的直接访问。抽象方法 init 用于初始化 Flea 策略实现 Map,该方法由Flea 策略抽象上下文的子类实现,并在策略上下文子类实例化时,调用该方法完成具体初始化的工作。

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* Flea抽象策略上下文,封装了公共的策略执行逻辑,
* 其中Flea策略Map由其子类进行初始化,键为策略名,
* 值为具体的Flea策略实例。
*
* @param <T> Flea策略执行结果对应的类型
* @param <P> Flea策略上下文参数
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public abstract class FleaStrategyContext<T, P> implements IFleaStrategyContext<T, P> {

private Map<String, IFleaStrategy<T, P>> fleaStrategyMap; // Flea策略Map

private P contextParam; // Flea策略上下文参数

/**
* 初始化策略上下文
*
* @since 1.1.0
*/
public FleaStrategyContext() {
fleaStrategyMap = init();
}

/**
* 初始化策略上下文
*
* @param contextParam Flea策略上下文参数
* @since 1.1.0
*/
public FleaStrategyContext(P contextParam) {
this();
this.contextParam = contextParam;
}

/**
* 初始化Flea策略Map
*
* @return Flea策略Map
* @since 1.1.0
*/
protected abstract Map<String, IFleaStrategy<T, P>> init();

@Override
public T invoke(String strategy) throws FleaStrategyException {
if (ObjectUtils.isEmpty(fleaStrategyMap)) {
throw new FleaStrategyException("The Strategy Map is not initialized!");
}
IFleaStrategy<T, P> fleaStrategy = fleaStrategyMap.get(strategy);
if (ObjectUtils.isEmpty(fleaStrategy)) {
throw new FleaStrategyNotFoundException("The Strategy [name =\"" + strategy + "\"] is not found!");
}
return fleaStrategy.execute(contextParam);
}

@Override
public void setContext(P contextParam) {
this.contextParam = contextParam;
}

@Override
public P getContext() {
return contextParam;
}
}

3.7 定义动物喊叫声策略上下文类

AnimalVoiceContext 动物喊叫声策略上下文,继承 Flea 抽象策略上下文,实现 init 方法,用于初始化 Flea 策略实现 Map,其中 key 为 策略名,value 为 具体的动物喊叫声策略实现类;Collections.unmodifiableMap 用于返回一个 只读Map

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
/**
* 动物喊叫声策略上下文
*
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class AnimalVoiceContext extends FleaStrategyContext<String, String> {

private static Map<String, IFleaStrategy<String, String>> fleaStrategyMap;

static {
fleaStrategyMap = new HashMap<>();
fleaStrategyMap.put("dog", new DogVoiceStrategy());
fleaStrategyMap.put("cat", new CatVoiceStrategy());
fleaStrategyMap.put("duck", new DuckVoiceStrategy());
fleaStrategyMap = Collections.unmodifiableMap(fleaStrategyMap);
}

public AnimalVoiceContext() {
}

public AnimalVoiceContext(String contextParam) {
super(contextParam);
}

@Override
protected Map<String, IFleaStrategy<String, String>> init() {
return fleaStrategyMap;
}
}

3.8 定义Flea策略门面

FleaStrategyFacade 定义 Flea 策略调用的统一入口

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
/**
* Flea策略门面,定义策略调用的统一入口。
*
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class FleaStrategyFacade {

private FleaStrategyFacade() {
}

/**
* 策略门面调用方法
*
* @param strategy 策略名
* @param fleaStrategyContext 策略上下文
* @param <T> Flea策略执行结果对应的类型
* @param <P> Flea策略上下文参数
* @return Flea策略执行结果对应的类型
* @throws FleaStrategyException Flea策略异常
* @since 1.1.0
*/
public static <T, P> T invoke(String strategy, IFleaStrategyContext<T, P> fleaStrategyContext) throws FleaStrategyException {
return fleaStrategyContext.invoke(strategy);
}
}

4. 测试

单元自测类可查看 FleaStrategyTest

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
/**
* @author huazie
* @version 1.1.0
* @since 1.1.0
*/
public class FleaStrategyTest {

private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(FleaStrategyTest.class);

@Test
public void testStrategy() {

AnimalVoiceContext context = new AnimalVoiceContext("旺财");
LOGGER.debug(FleaStrategyFacade.invoke("dog", context));

context.setContext("Tom");
LOGGER.debug(FleaStrategyFacade.invoke("cat", context));

AnimalVoiceContext context1 = new AnimalVoiceContext();
context1.setContext("Donald");
LOGGER.debug(FleaStrategyFacade.invoke("duck", context1));

}
}

单元测试类运行结果如下:

总结

好了,通用策略模式模式实现–Flea Strategy 已讲解完毕,欢迎大家使用 !