
被迫重构代码,这次我干掉了 if-else
最近公司貌似融到资了!开始发了疯似的找渠道推广,现在终于明白为啥前一段大肆的招人了,原来是在下一盘大棋,对员工总的来看是个好事,或许是时候该跟boss提一提涨工资的话题了。
不过,涨工资还没下文,随之而来的却是一车一车的需求,每天都有新渠道接入,而且每个渠道都要提供个性化支持,开发量陡增。最近都没什么时间更文,准点下班都成奢望了!由于推广渠道的激增,而每一个下单来源在下单时都做特殊的逻辑处理,可能每两天就会加一个来源,已经把之前的下单逻辑改的面目全。出于长远的考虑,我决定对现有的逻辑进行重构,毕竟长痛不如短痛。
传统的实现方式
我们看下边的伪代码,大致就是重构前下单逻辑的代码,由于来源比较少,简单的做if-else
逻辑判断足以满足需求。
现在每种订单来源的处理逻辑都有几百行代码,看着已经比较臃肿,可我愣是迟迟没动手重构,一方面业务方总像催命鬼一样的让你赶工期,想快速实现需求,这样写是最快;另一方面是不敢动,面对古董
级代码,还是想求个安稳。
但这次来源一下子增加几十个,再用这种方式做已经无法维护了,想象一下那种臃肿的if-else
代码,别说开发想想都头大!
策略模式的实现方式
思来想去基于当前业务场景重构,还是用策略模式比较合适,它是oop
中比较著名的设计模式之一,对方法行为的抽象。
策略模式定义了一个拥有共同行为的算法族,每个算法都被封装起来,可以互相替换,独立于客户端而变化。
一、策略模式的使用场景:
- 针对同一问题的多种处理方式,仅仅是具体行为有差别时;
- 需要安全地封装多种同一类型的操作时;
- 同一抽象类有多个子类,而客户端需要使用
if-else
或者switch-case
来选择具体子类时。
这个是用策略模式修改后代码:
每个订单来源都有自己单独的逻辑实现类,而每次需要添加订单来源,直接新建实现类,修改@OrderHandlerType(16)
的数值即可,再也不用去翻又臭又长的if-lese
。
不仅如此在分配任务时,每个人负责开发几种订单来源逻辑,都可以做到互不干扰,而且很大程度上减少了合并代码的冲突。
二、具体的实现过程:
1、定义注解
定义一个标识订单来源的注解@OrderHandlerType
2、抽象业务处理器
向上抽象出来一个具体的业务处理器
3、项目启动扫描 handler
入口
4、扫描需要用到的工具类
5、根据类型实例化抽象类
6、调用入口
我这里是在接受到MQ消息时,处理多个订单来源业务,不同订单来源路由到不同的业务处理类中。
接收实体 MessageBean
类代码
以上设计模式方式看着略显复杂,很些小伙伴提出质疑:“你为了个if-else
,弄的如此的麻烦,又是自定义注解,又弄这么多类不麻烦吗?” 还有一些小伙伴纠结于性能问题,策略模式的性能可能确实不如if-else
。
但我觉得吧增加一点复杂度、牺牲一丢丢性能,换代码的整洁和可维护性还是值得的。不过,一个人一个想法,怎么选还是看具体业务场景吧!
策略模式的优缺点
优点
- 易于扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合开放封闭原则
- 避免使用多重条件选择语句,充分体现面向对象设计思想 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换
- 每个策略类使用一个策略类,符合单一职责原则 客户端与策略算法解耦,两者都依赖于抽象策略接口,符合依赖反转原则
- 客户端不需要知道都有哪些策略类,符合最小知识原则
缺点
- 策略模式,当策略算法太多时,会造成很多的策略类
- 客户端不知道有哪些策略类,不能决定使用哪个策略类,这点可以通过封装common公共包解决,也可以考虑使
IOC容器
和依赖注入
的方式来解决。
以下是订单来源策略类的一部分,不得不说策略类确实比较多。
总结
凡事都有他的两面性,if-else
多层嵌套和也都有其各自的优缺点:
-
if-else
的优点就是简单,想快速迭代功能,逻辑嵌套少且不会持续增加,if-else
更好些,缺点也是显而易见,代码臃肿繁琐不便于维护。 -
策略模式
将各个场景的逻辑剥离出来维护,同一抽象类有多个子类,需要使用if-else
或者switch-case
来选择具体子类时,建议选策略模式,他的缺点就是会产生比较多的策略类文件。
两种实现方式各有利弊,如何选择还是要依据具体业务场景,还是那句话设计模式不是为了用而用,一定要用在最合适的位置。
文章转载自公众号:程序员小富
