对于业务开发来说,业务逻辑的复杂是必然的 。随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多 if-else 。

文章插图
图片来自 Pexels
一旦代码中 if-else 过多,就会大大的影响其可读性和可维护性 。

文章插图
首先可读性,不言而喻,过多的 if-else 代码和嵌套,会使阅读代码的人很难理解到底是什么意思 。尤其是那些没有注释的代码 。
其次是可维护性,因为 if-else 特别多,想要新加一个分支的时候,就会很难添加,极其容易影响到其他的分支 。
笔者曾经看到过一个支付的核心应用,这个应用支持了很多业务的线上支付功能,但是每个业务都有很多定制的需求,所以很多核心的代码中都有一大坨 if-else 。
每个新业务需要定制的时候,都把自己的 if 放到整个方法的最前面,以保证自己的逻辑可以正常执行 。这种做法,后果可想而知 。
其实,if-else 是有办法可以消除掉的,其中比较典型的并且使用广泛的就是借助策略模式和工厂模式,准确的说是利用这两个设计模式的思想,彻底消灭代码中的 if-else 。
本文就结合这两种设计模式,介绍如何消除 if-else,并且,还会介绍如何和 Spring 框架结合,这样读者看完本文之后就可以立即应用到自己的项目中 。
本文涉及到一些代码,但是作者尽量用通俗的例子和伪代码等形式使内容不那么枯燥 。
恶心的 if-else
假设我们要做一个外卖平台,有这样的需求:
- 外卖平台上的某家店铺为了促销,设置了多种会员优惠,其中包含超级会员折扣 8 折、普通会员折扣 9 折和普通用户没有折扣三种 。
- 希望用户在付款的时候,根据用户的会员等级,就可以知道用户符合哪种折扣策略,进而进行打折,计算出应付金额 。
- 随着业务发展,新的需求要求专属会员要在店铺下单金额大于 30 元的时候才可以享受优惠 。
- 接着,又有一个变态的需求,如果用户的超级会员已经到期了,并且到期时间在一周内,那么就对用户的单笔订单按照超级会员进行折扣,并在收银台进行强提醒,引导用户再次开通会员,而且折扣只进行一次 。
public BigDecimal calPrice(BigDecimal orderPrice, String buyerType) { if (用户是专属会员) { if (订单金额大于30元) { returen 7折价格; } } if (用户是超级会员) { return 8折价格; } if (用户是普通会员) { if(该用户超级会员刚过期并且尚未使用过临时折扣){ 临时折扣使用次数更新(); returen 8折价格; } return 9折价格; } return 原价; } 以上,就是对于这个需求的一段价格计算逻辑,使用伪代码都这么复杂,如果是真的写代码,那复杂度可想而知 。
这样的代码中,有很多 if-else,并且还有很多的 if-else 的嵌套,无论是可读性还是可维护性都非常低 。那么,如何改善呢?
策略模式
接下来,我们尝试引入策略模式来提升代码的可维护性和可读性 。
首先,定义一个接口:
/** * @author mhcoding */ public interface UserPayService { /** * 计算应付价格 */ public BigDecimal quote(BigDecimal orderPrice); } 接着定义几个策略类:
/** * @author mhcoding */ public class ParticularlyVipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { if (消费金额大于30元) { return 7折价格; } } } public class SuperVipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { return 8折价格; } } public class VipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { if(该用户超级会员刚过期并且尚未使用过临时折扣){ 临时折扣使用次数更新(); returen 8折价格; } return 9折价格; } } 引入了策略之后,我们可以按照如下方式进行价格计算:
/** * @author mhcoding */ public class Test { public static void main(String[] args) { UserPayService strategy = new VipPayService(); BigDecimal quote = strategy.quote(300); System.out.println("普通会员商品的最终价格为:" + quote.doubleValue()); strategy = new SuperVipPayService(); quote = strategy.quote(300); System.out.println("超级会员商品的最终价格为:" + quote.doubleValue()); } } 以上,就是一个例子,可以在代码中 New 出不同的会员的策略类,然后执行对应的计算价格的方法 。
推荐阅读
- MySQL中七个查询命令的优先级及特点
- 千万级MySQL数据库建立索引,提高性能的秘诀
- 开发者必须了解的22个常用小程序开发api接口
- Nginx 模块的基本结构
- 通过监控DNS记录,来保护网站的几种方式?你需要了解
- 细说HTTP协议及其工作流程
- 5 种用 CSS 隐藏页面元素的方法
- 瓷砖用什么擦会发亮,瓷砖脏的发黑怎么清理
- 什么是窗户的k值,门窗k值一般是多少
- 床单用法兰绒的好吗,婴儿能睡法兰绒床单吗
