设计模式-策略模式实战

策略模式概念 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); 至此,完成了业务上的需求,同时后期如果还有其它类型的开门方式,可以直接写实现类,不用改之前的代码,维护起来比较方便。 ...

<span title='2022-03-03 18:30:14 +0800 +0800'>March 3, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;YuanPeng11