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

2023-05-16

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<String, IEventService> 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、缺点

  • 策略模式,当策略算法太多时,会造成很多的策略类
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java运用策略模式+简单工厂消除if-else 的相关文章

  • Vue指令之v-on篇

    说到v on就立马事件 xff0c 最典型的的例子就是按钮的事件我们可以用v on监听事件 xff0c 并对用户的输入进行响应 先举个例子 xff0c 上代码 xff1a lt html gt lt head gt lt meta char
  • Vue指令之v-bind篇

    v bind指令 xff0c bind中文意思是捆绑的意思 xff0c 额 xff0c 捆绑 其绑定的参数在v bind 指令中的maohao xff08 冒号 xff09 后指明 xff0c 没错就是我标红的那个冒号 v bind指令被用
  • 5分钟认识JSON

    JSON JavaScript Object Notation JavaScript 对象表示法 什么是Json Json是java script 对象表示式 json是轻量级的文本数据交换格式 json对立于语言 xff1a json使用
  • JS中的const、var和let的区别

    看项目的时候遇到了const和let不知道什么意思 xff0c 特写此博客给记忆力不好的我 1 const定义的变量不可以修改 xff0c 而且补习初始化 xff08 相当于java中的常量 xff09 const a 61 2 正确 a
  • SpringMVC执行的流程

    先通过一个流程图来介绍请求 响应的完整流程 该图是SpringMVC请求响应的完整流程 工作流程如下 xff1a 1 用户向服务器发送请求 xff0c 请求被前端控制器DispatcherServlet截获 2 DispatcherServ
  • SpringMVC之@Controller注解

    Spring从2 5版开始引入注解 xff0c 本文说的是SpringMVC 4版 64 Controller注解 Controller注解用于指示Spring类的实例是一个控制器 xff0c 相对于实现Controller接口变得更加简单
  • SpringMVC之@RequestMapping注解

    RequestMapping xff1a org springframework web bind annotation RequestMapping RequestMapping注解类型用来指示Spring用哪一个类或方法来处理请求动作
  • Model和ModelAndView

    在 64 RequestMapping注解的方法中 xff0c 可出现和返回的参数类型中 xff0c 最重要的就是Model和ModelAndView了 SpringMVC在内部使用了一个Model接口存储模型数据 xff0c 它的功能类似
  • 解决 GTS GtsPermissionTestCases 模块 testPreloadedAppsTargetSdkVersion fail 问题

    报错报告截图 xff1a 解决办法 xff1a 重新生成 release platform shared media 4对签名文件替换 span class token number 1 span 重新替换release platform
  • @RequestParam注解

    在一些业务场景下 xff0c 前端发送请求的属性名称和后端方法接收参数名不相同 xff0c 这时候就要用到 64 RequestParam注解将后端的参数名重命名为前端对应的参数名称 xff01 org springframework we
  • Photoshop安装包破解安装教程

    详细的Photoshop安装包获取及破解安装过程 xff0c 请看大神的链接 https blog csdn net cssavage article details 81508689 本人亲测 xff0c 着实可靠 xff01 xff01
  • MySQL连接查询—自身连接

    若一个查询同时涉及两个表及以上的表 xff0c 则称之为连接查询 连接查询是关系数据库中最主要的查询 xff0c 包括等值连接查询 自然连接查询 非等值连接查询 自身连接查询 外连接查询和复合条件查询等 1 等值于非等值连接查询 连接查询的
  • CSS选择器

    CSS的选择器包括两种 xff1a Id和Class 1 ID选择器 id选择器可以标有特定ID的HTML元素指定特定的样式 HTML元素以ID属性来设置ID选择器 xff0c CSS中ID选择器以 来定义 以下选择器规则应用于元素属性id
  • CSS的创建

    当读到一个样式表时 xff0c 浏览器会根据样式表来美化HTML页面 本文就对插入样式表的三种方法做介绍 xff1a 首先 xff0c 先说一下三种方法为 xff1a 外部样式表 内部样式表 内联样式 1 外部样式表 应用场景 xff1a
  • CSS列表样式

    CSS列表属性作用如下 设置不同的列表项标记为有序列表设置不同的列表项标记为无序列表设置列表项标记为图像 无序列表 xff1a 用特殊图形标记列表项 有序列表 xff1a 用数字或字母标记列表项 CSS列表属性 属性描述list style
  • java虚拟机内存区域详解

    运行时数据区域 java虚拟机在执行java程序的过程中会把它管理的内存划分为若干个不同的数据区域 这些区域各自为政 xff0c 有的区域随着虚拟机进程的启动而存在 xff0c 而有些区域的生命周期则依赖于用户线程的生命周期 java虚拟机
  • csdn博客如何设置插入代码段的背景色

    最近在写博客的过程中发现自己插入的代码背景色全是米色的 xff0c 看起来很不爽 xff0c 就想要炫酷黑 经过一番研究 xff0c 终于发现如何设置插入代码段的背景颜色 xff1a 大体操作 xff1a 我的博客 gt 管理博客 gt 博
  • Exception in thread "main" java.lang.AbstractMethodError(Spring boot启动报错)

    具体报错 xff1a Exception in thread 34 main 34 java lang AbstractMethodError org springframework boot context config ConfigFi
  • Unregistering JMX-exposed beans on shutdown Disconnected from the target VM(springboot启动报错: )

    具体报错 xff1a Unregistering JMX exposed beans on shutdown Disconnected from the target VM address 39 127 0 0 1 52998 39 tra
  • python排序算法——归并排序(附代码)

    python排序算法 归并排序 文章目录 python排序算法 归并排序一 前言二 算法描述三 代码实现总结 一 前言 相关知识来自 python算法设计与分析 初级排序算法是指几种较为基础且容易理解的排序算法 初级排序算法包括插入排序 选

随机推荐

  • springboot使用fastjson解析json中文乱码问题

    使用fastjson解析json 需要在配置文件application properties中添加 spring http encoding force 61 true 否则 中文会出现乱码
  • springboot访问数据库报 Invalid bound statement (not found)

    如果在使用mapper xml时报了Invalid bound statement not found 的错误 xff0c 并且自己的mapper xml的路径和文件名都没有错误的情况 xff0c 很可能是因为没有在pom xml中配置如下
  • springboot项目创建

    1step xff1a File gt New gt project 2step 在New Project窗口选择Spring Initializer gt 选择default gt Next 3step 命名好项目名等信息点击 Next
  • SpringBoot存入数据库问号问题

    将resources目录下的application properties配置文件中数据库URL配置改为 xff1a spring datasource url 61 jdbc mysql localhost 3306 student use
  • 线程之wait/notify机制

    什么是等待 通知机制 举个栗子 xff1a 餐厅里 xff0c 厨师做好菜之后 xff0c 通知等待中的服务员就是一个简单的等待通知机制 wait xff1a wait方法代码的作用是使当前执行代码的线程进入等待 xff0c wait方法是
  • MySQL常用函数

    开始来熬大骨汤 xff0c 每周一碗大骨汤 xff0c 你也能变成光 于南京 MySQL函数的位置 xff1a 函数可以在select语句及其子句 xff08 例如 where order by having等 xff09 中 xff0c
  • idea的Browse Repositories搜索下载安装插件失败

    我在下载一个插件时 xff0c 刚开始出先下载超时time out xff0c 后来改了一些东西 xff0c 在Browse Repositories界面中 xff0c 直接搜不到插件了 xff08 一个插件都搜不到 xff09 xff0c
  • 安装goole浏览器报错

    1 下载一个谷歌的rpm包 xff0c 配置repo源 root 64 physical cat etc yum repos d google chrome repo google chrome name 61 google chrome
  • 经典编程书籍(C++, 网络, Windows, Linux)

    导读 xff1a 书单中列举的都是相关领域的经典书籍 xff0c 必读之作 此书单的编辑参考了很多网站 xff0c 包括一些名家的推荐 xff0c 例如侯捷 xff0c 孟岩 xff0c 荣耀 xff0c 潘爱民等等 xff0c 在此也向这
  • 域名+解析+GitHub来搭建自己的个人网站

    摘要 文章主要介绍域名解析 xff0c 使用GitHub上的开源项目来搭建一个个人博客 并不需要购买服务器 xff0c 没有数据库访问 xff0c 适合搭建自己的博客或者个人网站 xff0c 不适合大型网站 购买域名 可以在万网上面注册一个
  • Linux服务器批量管理工具 - TeamRemote

    产生背景 xff1a 当前网上流行的一些优秀且功能强大的工具 xff0c 如puppet xff0c dsh xff0c parallel ssh xff0c ansible等 但不得不说 xff0c 他们的上手起来太复杂了 xff0c 导
  • C语言书籍推荐

    C 语言书籍推荐 宗旨 xff1a 技术的学习是有限的 xff0c 分享的精神是无限的 一 基础 1 C语言入门很简单 零起点学通C语言 xff08 多媒体范例教学 xff09 C语言从入门到精通 2 C程序设计语言 第2版 新版 C程序设
  • MATLAB排序函数

    MATLAB排序函数 2011 06 29 13 02 08 源自网络 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • 具有FTP、FTPS和sftp功能的文本编辑器——EditPlus功能介绍

    EditPlus是Windows的文本编辑器 xff0c 具有内置的FTP FTPS和sftp功能 虽然它可以很好地替代记事本 xff0c 但它也为网页作者和程序员提供了许多强大的功能 功能特征 01 语法高亮 EditPlus 默认支持H
  • 《iOS高级编程》中的内存管理基础【MRC】

    文章目录 关于我的仓库前言准备工作内存管理 引用计数 的思考 p 2 p 13 记住一张表格内存管理四大原则注意点疑点 内存管理四兄弟 alloc retain release dealloc p 13 p 20 说明alloc计数GNU实
  • python获取指定路径的文件夹下所有TXT文本内容

    有时候 xff0c 我们需要读取某个指定路径的文件夹下的所有txt的文本内容 xff0c 具体步骤 xff1a 可以使用os listdir 方法先获取文件夹下所有文本的文件名 xff0c 然后循环遍历文件名 xff0c 使用open 方法
  • 生物识别传感器 安全性要求背景

    7 3 10 生物识别传感器 如需了解衡量生物识别解锁模式的安全性的其他背景 xff0c 请参阅衡量生物识别的安全性文档 如果设备实现包含安全锁定屏幕 xff0c 则 xff1a 应包含生物识别传感器 生物识别传感器可基于其欺骗和冒名攻击的
  • 笔记本win10 睡眠时会自动唤醒?修复后唤醒缓慢也解决了

    家里笔记本 xff08 Dell XPS13 xff09 xff0c 睡眠后就睡觉了 醒来后 xff0c 发现电池一直耗电 xff1f xff01 查看 Event Viewer 34 xff0c 看到睡眠后几秒钟就自动唤醒了 xff0c
  • Python每日一个小程序

    前几天上网 xff0c 收集了20多道Python练习题 这些练习题还是很有价值的 xff0c 正好最近忙着复习准备校招 xff0c 可以用来练手 我会把每道题都写一篇博客详细阐述解题思路和源代码 xff0c 在每道题目后面附上博客地址 希
  • Java运用策略模式+简单工厂消除if-else

    1 问题场景 监听上游服务MQ消息 xff0c 根据不同的操作类型 xff08 opCode xff09 做相对应的个性化处理 目前接收的就三种 xff0c 随着业务拓展还会不断的增加 xff0c 所以此处按照原来的if else去处理会显