利用策略模式优化过多 if else 代码
前言
不出意外,这应该是年前最后一次分享,本次来一点实际开发中会用到的小技巧。
比如平时大家是否都会写类似这样的代码:
if(a){
//dosomething
}else if(b){
//doshomething
}else if(c){
//doshomething
} else{
////doshomething
}
条件少还好,一旦 else if
过多这里的逻辑将会比较混乱,并很容易出错。
比如这样:
摘自 cim 中的一个客户端命令的判断条件。
刚开始条件较少,也就没管那么多直接写的;现在功能多了导致每次新增一个 else
条件我都得仔细核对,生怕影响之前的逻辑。
这次终于忍无可忍就把他重构了,重构之后这里的结构如下:
最后直接变为两行代码,简洁了许多。
而之前所有的实现逻辑都单独抽取到其他实现类中。
这样每当我需要新增一个 else
逻辑,只需要新增一个类实现同一个接口便可完成。每个处理逻辑都互相独立互不干扰。
实现
按照目前的实现画了一个草图。
整体思路如下:
- 定义一个
InnerCommand
接口,其中有一个process
函数交给具体的业务实现。 - 根据自己的业务,会有多个类实现
InnerCommand
接口;这些实现类都会注册到Spring Bean
容器中供之后使用。 - 通过客户端输入命令,从
Spring Bean
容器中获取一个InnerCommand
实例。 - 执行最终的
process
函数。
主要想实现的目的就是不在有多个判断条件,只需要根据当前客户端的状态动态的获取 InnerCommand
实例。
从源码上来看最主要的就是 InnerCommandContext
类,他会根据当前客户端命令动态获取 InnerCommand
实例。
- 第一步是获取所有的
InnerCommand
实例列表。 - 根据客户端输入的命令从第一步的实例列表中获取类类型。
- 根据类类型从
Spring
容器中获取具体实例对象。
因此首先第一步需要维护各个命令所对应的类类型。
所以在之前的枚举中就维护了命令和类类型的关系,只需要知道命令就能知道他的类类型。
这样才能满足只需要两行代码就能替换以前复杂的 if else
,同时也能灵活扩展。
InnerCommand instance = innerCommandContext.getInstance(msg);
instance.process(msg) ;
总结
当然还可以做的更灵活一些,比如都不需要显式的维护命令和类类型的对应关系。
只需要在应用启动时扫描所有实现了 InnerCommand
接口的类即可,在 cicada 中有类似实现,感兴趣的可以自行查看。
这样一些小技巧希望对你有所帮助。
以上所有源码可以在这里查看:
https://github.com/crossoverJie/cim
你的点赞与分享是对我最大的支持
利用策略模式优化过多 if else 代码的更多相关文章
- 代码重构:用工厂+策略模式优化过多的if else代码块
最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...
- 用工厂模式和策略模式优化过多的if-else
多个if-else代码: @RunWith(SpringRunner.class) @SpringBootTest public class EducationalBackgroundTest { p ...
- 策略模式优化过多的IF ELSE
前言: 当if else的条件少的话,代码可阅读性及逻辑不影响阅读和扩展.一旦if else过多的话会导致逻辑比较混乱,不易扩展并且很容易出错. 实现方案: 1.定义一个@HandlerType注解, ...
- 代码重构:用工厂+策略模式优化冗余的if else代码块
最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...
- 如何在Spring Boot项目中巧妙利用策略模式干掉if else!
直入主题 我们都知道,设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路.它不是语法规定,而是一套用来提高代码可复用性.可维护性.可读性.稳健性以及安全性 ...
- 设计模式之策略模式(iOS开发,代码用Objective-C展示)
在实际开发过程中,app需求都是由产品那边给出,往往是他给出第一版功能,我们写好代码后,会相应的给出第二版.第三版功能,而这些功能是在实际使用中,根据用户需求而不断增加的.如果在编码之初,我们并未认识 ...
- 利用策略模式实现了同一接口的多个Servicel实现类,如何同时注入Controller
解决方法如上图,通过给实现类起别名,并在controller中,通过@Qualifier注解获取不同的实现类,之前没有这样写,会出现这样的情况: 通过@autowired注解注入dao层时为空,会报空 ...
- SpringBoot自定义初始化Bean+HashMap优化策略模式实践
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 传统的策略模式一般是创建公共接口.定义公共方法-->然后创建实体类实现公共接口.根据各自的 ...
- Android 设计模式实战之关于封装计费代码库的策略模式详谈
写在之前 这周生活上出现了很多的不如意,从周一开始就觉得哪里出现了问题,然后就是各种烦躁的情绪,后来事情还真是如预感的那样发生了,很是心痛,但也无可奈何,希望大家都好好珍惜自己身边的人:友人,亲人,家 ...
随机推荐
- java数据库之JDBC
任何一个项目,都离不开数据,而对于数据的存储以及其他操作,就会用到数据库了. 在这里是主要针对MySQL数据库的操作. 1.软件 当然首先要下载MySQL,为了操作起来更加方便,这里推荐一个比较方便的 ...
- 学习CountDownLatch
对比 使用CyclicBarrier 上次用Barrier方式实现了线程等待一组完成,这次用CountDownLatch来实现 我的理解CountDownLatch 采用的方式是计数器方式,每执行完一 ...
- 让 Homebrew 走代理更新 + brew 管理 node 版本
0.前言 环境:MacOS 背景:整理下今天所做的配置. 1. 让 Homebrew 走代理更新 brew update 就卡住了,即使开了 shadowsocks 也不行.因为 shadowsock ...
- 15.linux基础
1.目录 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始.当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始,再进入到home目录 ...
- TCP/IP Http 和Https socket之间的区别
TCP/IP Http 和Https socket之间的区别 TCP/IP是个协议组,它分为网络层,传输层和应用层, 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. ...
- SpringMVC中利用@CrossOrigin注解解决ajax跨域请求的问题
1. 什么是跨域 跨域,即跨站HTTP请求(Cross-site HTTP request),指发起请求的资源所在域不同于请求指向资源所在域的HTTP请求. 2. 跨域的应用情景 当使用前后端分离,后 ...
- SSM-MyBatis-10:Mybatis中SqlSession的getMapper()和简单的工具类MyBatisUtils
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- getMapper的作用,获取到接口,直接通过点的方式调用方法,以免直接手打的方式写错方法名,(强类型的方式) ...
- elasticsearch 的安装配置与spring boot的整合应用
linux上的elasticsearch安装 一.下载elasticsearch 直接进入elasticsearch的官网,下载最新的安装包:https://www.elastic.co/downlo ...
- Java 精简Jre jar打包成exe
#开始 最近几天都在忙一个事情,那就是尝试精简jre,我想不明白为什么甲骨文官方不出exe打包工具... 网络上精简jre的文章很多,但是原创的似乎没几个,绝大多数都是转发同一个博客, 这里借鉴了不少 ...
- call(),apply()方法解析(一)
1.call()和apply()的作用是改变this指向,区别是传参列表不同(前者连续参数,后者为参数数组) 2.方法定义: function.apply(thisObj[, argArray]) f ...