栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java运用策略模式+简单工厂消除if-else

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java运用策略模式+简单工厂消除if-else

1、问题场景

        监听上游服务MQ消息,根据不同的操作类型(opCode)做相对应的个性化处理。目前接收的就三种,随着业务拓展还会不断的增加,所以此处按照原来的if-else去处理会显得比较呆。

2、一般实现(if-else)
public Action consume(Message message, ConsumeContext context) {
        boolean success = true;
        long startTime = System.currentTimeMillis();
        try {
            String content = new String(message.getBody(), StandardCharsets.UTF_8);
            log.info("op_message_listener receive_msg: {}", content);
            DetailsDO detailsDO = JSONObject.parseObject(content, DetailsDO.class);
            String opCode = detailsDO.getOpCode().getCode();
            if (OpCodeEnum.OP_CODE_100.getCode().equals(opCode)) {
                opCode_100(detailsDO);
            } else if (OpCodeEnum.OP_CODE_110.getCode().equals(opCode)) {
                opCode_110(detailsDO);
            } else if (OpCodeEnum.OP_CODE_120.getCode().equals(opCode)) {
                opCode_120(detailsDO);
            }
        } catch (Exception e) {
            success = false;
            log.error("op_message_listener handle_error", e);
        }
        MonitorLogUtil.addSunFireLog("op_message_listener_事件操作消息监听" + "#" + "message.getMsgID()", startTime, success);
        return (success || !errorRetry) ? Action.CommitMessage : Action.ReconsumeLater;
}

以上代码实现有如下的缺点:

  • 不易于扩展,增加一个新的渠道需要改变原有的代码,不符合开放封闭原则
  • 使用多重条件选择语句,随着业务拓展if-else会越来越多,不符合面向对象设计思想

  • 代码糅合在一起,不利于阅读和维护,不符合单一职责原则

    针对以上代码的缺点我们可以利用策略模式来消除臃肿复杂的if-else。

    3、策略+简单工厂

            策略模式(Strategy Pattern)定义了一组策略,分别在不同类中封装起来,每种策略都可以根据当前场景相互替换,从而使策略的变化可以独立于操作者。比如我们要去某个地方,会根据距离的不同(或者是根据手头经济状况)来选择不同的出行方式(共享单车、坐公交、滴滴打车等等),这些出行方式即不同的策略。

            简单工厂提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。

    3.1、定义抽象的数据策略接口
    public interface IEventService {
    
        void opHandler(DetailsDO detailsDO);
    
        String getOpCode();
    
    }

    其中的opHandler方法是执行具体匹配数据逻辑的接口

    3.2、具体策略实现类
    @Slf4j
    @Service("xxxEventService")
    public class XxxEventServiceImpl implements IEventService {
    
        @Override
        public void opHandler(DetailsDO detailsDO) {
            // 业务逻辑实现
            System.out.println("------xxx opHandler------");
        }
        
        @Override
        public String getOpCode() {
            return OpCodeEnum.OP_CODE_100.getCode();
        }
        
    }
    3.3、定义策略工厂
    @Component
    public class EventServiceFactory implements InitializingBean, ApplicationContextAware {
    
        private ApplicationContext appContext;
    
        private static final Map EVENT_SERVICE_MAP = new HashMap<>(8);
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            appContext = applicationContext;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            // 将 Spring 容器中所有的 IEventService 注册到 EVENT_SERVICE_MAP
            appContext.getBeansOfType(IEventService.class)
                      .values()
                      .forEach(handler -> EVENT_SERVICE_MAP.put(handler.getOpCode(), handler));
        }
    
        public static IEventService getHandler(String opCode) {
            return EVENT_SERVICE_MAP.get(opCode);
        }
    }
    3.4、调用实现
    public Action consume(Message message, ConsumeContext context) {
            boolean success = true;
            long startTime = System.currentTimeMillis();
            try {
                String content = new String(message.getBody(), StandardCharsets.UTF_8);
                log.info("op_message_listener receive_msg: {}", content);
                DetailsDO detailsDO = JSONObject.parseObject(content, DetailsDO.class);
                String opCode = detailsDO.getOpCode().getCode();
                // 替换if-else --begin
                IEventService eventService = EventServiceFactory.getHandler(opCode);
                eventService.opHandler(detailsDO);
                // 替换if-else --end
            } catch (Exception e) {
                success = false;
                log.error("op_message_listener handle_error", e);
            }
            MonitorLogUtil.addSunFireLog("op_message_listener_事件操作消息监听" + "#" + "message.getMsgID()", startTime, success);
            return (success || !errorRetry) ? Action.CommitMessage : Action.ReconsumeLater;
        }

    4、优缺点总结 4.1、优点

  • 易于扩展,增加一个新的策略只需要添加一个具体的策略实现类即可,基本不需要改变原有的代码,符合开放封闭原则
  • 避免使用多重条件选择语句,充分体现面向对象设计思想

  • 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换
  • 每个策略类使用一个策略类,符合单一职责原则

  • 客户端与策略算法解耦,两者都依赖于抽象策略接口,符合依赖反转原则
  • 客户端不需要知道都有哪些策略类,符合最小可用原则 4.1、缺点

  • 策略模式,当策略算法太多时,会造成很多的策略类
  • 转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/748947.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号