策略模式概念#
https://refactoringguru.cn/design-patterns/strategy
实战应用#
健康码组件对接的前端门禁设备都多种开门的方式,刷证,人脸,二维码等。对于每一种开门方式,其需要的返回结果是一样的,只是内部的处理方式不一样。所以这里使用策略模式+工厂模式来实现,通过一个入口以及不同的type来实现调用不同的实现类。具体代码如下。
1. 创建一个Handler接口类#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/**
* @Author Yuanpeng
* @Description 处理健康码请求携带参数的类 根据不同的类型进行 不同的处理
* @Date 2022/1/10
*/
public interface HealthCodeHandler {
/**
* 处理健康码信息的逻辑
* @param query 前置信息
* @return 处理的结果 包括开门信息 健康码信息 核酸信息 疫苗信息等
*/
HealthCodeResult handle(HealthCodeQuery query);
/**
* 获取请求的类型 1.人员唯一标识 personId 2.身份证号 3.二维码 4.人员卡号 5.人脸图片 6.市民卡
* @return 类型
*/
Integer getType();
}
|
2. 创建不同的Handler实现类,这里以二维码的实现类举例#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* @Author Yuanpeng
* @Description 处理二维码的实现类
* @Date 2022/1/10
*/
@Service
public class QrCodeHandler implements HealthCodeHandler {
private static final Logger log = LoggerFactory.getLogger(QrCodeHandler.class);
@Override
public HealthCodeResult handle(HealthCodeQuery query) {
HealthCodeResult result = ResultUtils.getDefaultHeathCodeResult(query, false);
// logic code
return result;
}
@Override
public Integer getType() {
return HealthCodeConstants.QR_CODE_TYPE;
}
|
3. 将所有实现了Handler接口类的实例注入容器#
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
|
/**
* @Author Yuanpeng
* @Description 策略模式的工厂类 加载所有的HealthCodeHandler类
* @Date 2022/1/10
*/
@Component
public class HealthCodeHandlerFactory implements InitializingBean, ApplicationContextAware {
private static final Map<Integer, HealthCodeHandler> HEALTH_CODE_HANDLER_MAP = new HashMap<>(6);
private ApplicationContext appContext;
/**
* 根据健康码信息类型获取对应的处理器
*
* @param type 健康码信息类型
* @return 健康码信息类型对应的处理器
*/
public HealthCodeHandler getHandler(Integer type) {
return HEALTH_CODE_HANDLER_MAP.get(type);
}
@Override
public void afterPropertiesSet() {
// 将 Spring 容器中所有的 HealthCodeHandler 注册到 FORM_SUBMIT_HANDLER_MAP
appContext.getBeansOfType(HealthCodeHandler.class)
.values()
.forEach(handler -> HEALTH_CODE_HANDLER_MAP.put(handler.getType(), handler));
}
@Override
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
appContext = applicationContext;
}
}
|
4. 入口处根据传参中的type进行不同类的调用#
1
2
3
|
// 使用策略模式来实现对不同类型请求的处理,如果需要添加其它类型信息的处理 只需要实现相应的HealthCodeHandler即可
HealthCodeHandler handler = healthCodeHandlerFactory.getHandler(query.getCardNoType());
HealthCodeResult result = handler.handle(query);
|
至此,完成了业务上的需求,同时后期如果还有其它类型的开门方式,可以直接写实现类,不用改之前的代码,维护起来比较方便。