为了业务的发展,业务逻辑的复杂化是不可避免的。随着业务的发展,需求只会越来越复杂。为了考虑各种情况,难免会有很多if-else。一旦代码中出现过多的if-else,就会极大地影响其可读性和可维护性。首先是可读性,不用说过多的if-else代码和嵌套会让阅读代码的人难以理解其中的含义。特别是那些没有注释的代码。其次是可维护性,因为if-else太多了,当你想增加一个新的分支时,会很难增加,极易影响其他分支。笔者曾经看过一个支付核心应用,它支持很多商家的在线支付功能,但是每个商家都有很多的定制需求,所以很多核心代码都有很多if-else。当每一个新的业务需要定制的时候,把自己的if放在整个方法的最前面,保证你的逻辑能够正常执行。这种做法的后果可想而知。事实上,有办法消除if-else。典型和广泛使用的是策略模式和工厂模式的使用。准确的说,就是利用这两种设计模式的思想,彻底杜绝代码中的if-else。.本文结合这两种设计模式,介绍了如何剔除if-else,同时也介绍了如何与Spring框架相结合,以便读者看完本文后可以立即应用到自己的项目中。本文涉及一些代码,但作者尽量使用流行的示例和伪代码来使内容不那么枯燥。恶心的if-else假设我们要做一个外卖平台,我们有如下需求:1、外卖平台某店铺设置了多种会员优惠促销,包括20%的折扣超级会员和普通会员10%的折扣普通用户有三种折扣。2、希望用户在支付的时候,根据用户的会员级别,能够知道用户满足了哪种折扣策略,然后进行打折,计算出应付金额。3、随着业务的发展,新的需求要求专享会员必须在店铺订单金额大于30元时才能享受优惠。4、接下来还有一个异常需求。如果用户的超级会员已过期,且过期时间在一周以内,则用户的单笔订单将根据超级会员进行折扣,并在收银处进行强烈提醒,引导用户开通再次成为会员,优惠只进行一次。那么,我们可以看到如下伪代码:publicBigDecimalcalPrice(BigDecimalorderPrice,StringbuyerType){if(用户是尊享会员){if(订单金额大于30元){返还30%的价格;}}if(该用户为超级会员){return20%offPrice;}if(该用户为普通会员){if(该用户超级会员刚过期,临时折扣尚未使用){临时折扣使用次数更新();return20%offprice;}return10%offprice;}returnoriginalprice;}以上,就是针对这个需求的一段价格计算逻辑。使用伪代码是如此复杂。如果真的把代码写出来,复杂度可想而知。这样的代码中,if-else很多,if-else的嵌套也很多,可读性和可维护性都很低。那么,如何改进呢?策略模式接下来,我们尝试引入策略模式来提高代码的可维护性和可读性。首先定义一个接口:/***@authormhcoding*/publicinterfaceUserPayService{/***计算应付价格*/publicBigDecimalquote(BigDecimalorderPrice);}然后定义几个策略类:/***@authormhcoding*/publicclassParticularlyVipPayServiceimplementsUserPayService{@OverridepublicBigDecimalquote(BigDecimalorderPrice){if(消费金额大于30元){return30%offprice;}}}publicclassSuperVipPayServiceimplementsUserPayService{@OverridepublicBigDecimalquote(BigDecimalorderPrice){return20%offprice;}}publicclassVipPayServiceimplementsUserPayService{@OverridepublicBigDecimalquoteUserPayService{@OverridepublicBigDecimalquote)superexpireBigDecimalquote(member(BigDecimalif且临时优惠尚未使用){临时优惠使用号update();return20%offprice;}return10%offprice;}}引入策略后,我们可以这样计算价格:/***@authormhcoding*/publicclassTest{publicstaticvoidmain(String[]args){UserPayServicestrategy=newVipPayService();BigDecimalquote=strategy.quote(300);System.out.println("普通会员产品最终价格为:"+quote.doubleValue());strategy=newSuperVipPayService();quote=strategy.quote(300);System.out.println("超级会员商品最终价格为:"+quote.doubleValue());}}以上为示例,可以在代码中新建不同会员的策略类,然后执行相应的计算价格的方法。读者可以在文章《如何给女朋友解释什么是策略模式?》中了解本例以及策略模式的相关知识。但是如果真正用在代码中,比如在web项目中,上面的demo根本就不能直接使用。首先,在web项目中,我们上面创建的策略类都是由Spring管理的,我们不会自己新建实例。其次,在web项目中,如果真的要计算价格,还需要提前知道用户的会员级别,比如从数据库中查询会员级别,然后根据级别获取不同的策略类执行价格计算方法。那么,web项目中真正的价格计算,伪代码应该是这样的:){//伪代码:从Spring中获取超级会员的策略对象(SuperVipPayService.class);returnstrategy.quote(orderPrice);}if(vipType==普通会员){UserPayServicestrategy=Spring.getBean(VipPayService.class);returnstrategy.quote(orderPrice);}返回原价;}通过上面代码,我们发现,代码的可维护性和可读性似乎更好了,但是if-else似乎并没有降低。其实在之前的文章《如何给女朋友解释什么是策略模式?》中,我们介绍了策略模式的很多优点。但是,策略模式的使用还有一个比较大的缺点:客户端必须知道所有的策略类,并决定使用哪个策略类。这意味着客户端必须了解这些算法之间的区别,以便在正确的时间选择合适的算法类。也就是说,虽然在计算价格的时候没有if-else,但是在选择具体策略的时候难免有些if-else。另外,在上面的伪代码中,我们实现伪代码是从Spring获取会员的policy对象,那么代码是如何获取对应的Bean的呢?下面我们就看看如何借助Spring和工厂模式来解决上述问题。工厂模式为了方便我们从Spring获取UserPayService的各种策略类,我们创建一个工厂类:/***@authormhcoding*/publicclassUserPayServiceStrategyFactory{privatestaticMap
