无极4注册主管-无极荣耀娱乐-无极登录注册

    
admin

废品机械师,用战略+工厂完全替换事务杂乱的if-else

  6天前     305     0
简介:对于业务开发来说,业务逻辑的复杂是必然的,随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多if-else。一旦代码中if-else过多,就会大大的影响其可读性和可维护性。...

关于业务开发来说,业务逻辑的凌乱是必定的,跟着业务开展,需求只会越来越凌乱,为了考虑到各式各样的状况,代码中不可避免的会呈现许多if-else。

一旦代码中if-else过多,就会大大的影响其可读性和可保护性。

if-else代码块

首要可读性,显而易见,过多的if-else代码和嵌套,会使阅览代码的人很难了解究竟是什么意思。尤其是那些没有注释的代码。

其次是可保护性,由于if-else特别多,想要新加一个分支的时分,就会很难增加,极端简略影响到其他的分支。

笔者从前看到过一个付出的中心运用,这个运用支撑了许多业务的线上付出功用,可是每个业务都有许多定制的需求,所以许多中心的代码中都有一大坨if-else。

每个新业务需求定制的时分,都把自己的if放到整个办法的最前面,以确保自己的逻辑能够正常履行。这种做法,结果可想而知。

其实,if-else是有办法能够消除去的,其间比较典型的并且运用广泛的便是凭借战略办法和工厂办法,精确的说是运用这两个规划模死鱼眼式的思维,完全消除代码中的if-else。

本文,就结合这两种规划办法,介绍怎么消除if-else,并且,还会介绍怎么和Spring结构结合,这样读者看完本文之后就能够当即运用到自己的项目中。

本文涉及到一些代码,可是作者尽量用浅显的比方和伪代码等办法使内容不那么单调。

厌恶的if-else

假定咱们要做一个外卖渠道,有这样的需求:

1、外卖渠道上的某家店肆股海泛舟网易博客为了促销,设置了多种会员优惠,其间包含超级会员扣头8折、一般会员扣头9折和一般用户没有扣头三种。2、期望用户在付款的时分,依据用户的会员等级,就能够知道用户契合哪种扣头战略,从而进行打折,核算出敷衍金额。3、跟着业务开展,新的需求要求专属会员要在店肆下单金额大于30元的时分才能够享用优惠。4、接着,又有一个反常的需求,假如用户的超级会员现已到期了,并且到期时刻在一周内,那么就对用户的单笔订单依照超级会员进行扣头,并在收银台进行强提示,引导用户再次注册会员,并且扣头只进行一次。

那么,咱们能够看到以下伪代码:

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且还有许多的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) 2020年{
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出不同的会员的战略类,然后履行对应的核算价格的办法。这个比方以及战略办法的相关常识,读者能够在《怎么给女朋友解说什么是战略办法?》一文中学习。

可是,真实在代码中运用,比方在一个web项目中运用,上面这个Demo底子没办法直接用。

首要,在web项目中,上面咱们创立出来的这些战略类都是被Spring保管的,咱们不会自己去new一个实例出来。

其次,在web项目中,假如真要核算价格,也是要事先知道用户的会员等级,比方从数据库中查出会员等级,然后依据等级获取不同的战略类履行核算价格办法。

那么,web项目中真实的核算价格的话,伪代码应该是这样的:

/**
* @author mhcoding
*/
public BigDecimal calPrice(BigDecimal orderPrice,User user) {
String vipType = user.getVipType();
if (vipType == 鸡爪专属会员) {
//伪代码:从Sp废品机械师,用战略+工厂完全替换业务凌乱的if-elsering中获取超级会员的战略目标
UserPayService strategy = Spring.getBean(Partic白斩鸡的做法ularlyVipPayService.class);
return strategy.quote(orderPrice);
}
if (vipType == 超级会员) {
UserPayService strategy 废品机械师,用战略+工厂完全替换业务凌乱的if-else= Spring.getBean(SuperVipPayService.class);
return strategy.quote(orderPrice);
}
if (vipType == 一般会员) {
UserPayService strategy = Spring.getBean(VipPayService.class);
return strategy.quote(orderPrice);
}
return 原价;
}

通废品机械师,用战略+工厂完全替换业务凌乱的if-else过以上代码,咱们发现,代码可保护性和可读性如同是好了一些,可是如同并没有削减if-else啊。

其实,在之前的《怎么给女朋友解说什么是战略办法?》一文中,咱们介绍了许多战略办法的长处。可是,战略办法的运用上,仍是有一个比较大的缺陷的:

客户端有必要知道一切的战略类,并自行决定运用哪一个战略类。这就意味着客户端有必要了解这些算法的差异,以便当令挑选废品机械师,用战略+工厂完全替换业务凌乱的if-else恰当的算法类。

也便是说,虽然在核算价格的时分没有if-else了,可是挑选详细的战略的时分仍是不可避免的仍是要有一些if-else。

别的,上面的伪代码中,从Spring中获取会员的战略目标咱们是伪代码完成的,那么代码究竟该怎么获取对应的Bean呢?

接下来咱们看怎么凭借Spring和工厂办法,处理上面这些问题。

工厂办法

为了便利咱们从Spring中获取UserPayService的各个战略类,咱们创立一个工厂类:

/**
* @au拯救老公thor mhcoding
*/
public class UserPayServiceStrategyFactory {
private static Map services = new ConcurrentHashMap();
public static UserPayService getByUserType(String type){
return services.get(type);
}
public static void register(String userType,UserPayService us北京妇产医院erPayService){
Assert.notNull(userType,"userType can't b情中情e null");
services.put(userType,userPayService);
}
}

这个UserPayServiceStrategyFactory中界说了一个Map,用来保存一切的战略类的实例,并供给一个getByUserType办法,能够依据类型直接获取对应的类的实例。还有一个register办法,这个后边再讲。

有了这个工厂类之后,核算价格的代码即可得到大大的优化:

/**
* @author mhcoding
*/
public BigDecimal calPrice(BigDecimal orderPrice,User user) {
String vipType = 创世纪之兄弟恩怨user.getVipType();
UserPayService strategy = UserPayServiceStrategyFactory.getByU双一流serTyp王若林e(vipType);
return strategy.quote(orderPrice);
}

以上代码中,不再需求if-else了,拿到用户的vip类型之后,直接经过工厂的getByUserType办法直接调用就能够了。

经过战略+工厂,咱们的代码很大程度的优化了,大大提高了可读性和可保护性。

可是,上面还遗留了一个问题,那便是UserPayServiceStrategyFactory中用来保存一切的战略类的实例的Map是怎么被初始化的?各个战略的实例目标怎么塞进去的呢?

Spring Bean的注册

还记得咱们前面界说的UserPayServiceStrategyFactory中供给了的register办法吗?他便是用来注册战略服务的。梦见棺材

接下来,咱们就想办法调用register办法,把Spring经过IOC创立出来的Bean注册进去就行了。

这种需求,能够借用Spring种供给的InitializingBean接口,这个接口为Bean供给了特点初始化后的处理办法,它只包含afterPropertiesSet办法,但凡承继该接口的类,在bean的特点初始化后都会履行该办法。

那么,咱们将前面的各个战略类稍作改造即可:

/**
* @author mhcoding
*/
@Service
public class ParticularlyVipPayService implements UserPayService,InitializingBean {
@Override
public BigDecimal quote(BigDecimal orderPrice) {
if (消费金额大于30元) {
return 7折价格;
}
}
@Override
public void afterPropertiesSet() throws Exception {
UserPayServiceStrategyFactory.register("ParticularlyVip",this);
}
}
@Service
public class SuperVipPayService implements UserPayService ,InitializingBean{
@Override
public BigDecimal quote(BigDecimal orderPrice) {
return 8折价格;
}
@Override
public void afterPropertiesSet() throws Exception {
UserPayServiceStrategyFactory.register("SuperVip",this);
}
}
@Service
public class VipPayService implements UserPayService,InitializingBean {
@Override
public BigDecimal quote(BigDecimal orderPrice) {
if(该用户超级会员刚过期并且没有运用过暂时扣头){
暂时扣头运用次数更新();
returen 8折价格;
}
return 9折价格;
}
@Ov吐槽erride
public void afterPropertiesSet() throws Exception {
UserPayServiceStrategyFactory.register("Vipxbet星投",this);
}
}

只需求每一个策废品机械师,用战略+工厂完全替换业务凌乱的if-else略服务的完成类都完成InitializingBean接口,并完成其afterPropertiesSet办法,在这个办法中调用UserPayServiceStrategyFactory.register即可。

这样,在Spring初始化的时分,当创立VipPayService、SuperVipPayService和ParticularlyVipPayService的时分,会在Bean的特点初始化之后,把这个Bean注册到UserPayServiceStrategyFactory中。

以上代码,其实仍是有一些重复代码的,这儿边还能够引进模板办法办法进一步精简,这儿就不展开了。

还有便是,UserPayServiceStrategyFactory.register调用的时分,第一个参数需求传一个字符串,这儿的话其实也能够优化掉。比方运用枚举,或许在每个靖江天气预报策废品机械师,用战略+工厂完全替换业务凌乱的if-else略类中自界说一个getUserType办法,各自完成即可。

总结

本文,咱们经过战略办法、工厂办法以及Spring的InitializingBean,提高神仙肉了代码的可读性以及可保护性,完全消除了一坨if-else。

文中的这种做法,咱们能够马上测验起来,这种实践,是咱们日常开发中经常用到的,并且还有许多衍生的用法,也都十分好用。有奥迪q3报价时机后边再介绍。

其实,假如读者们对战略办法和工厂办法了解的话,文中运用的并不是严厉意义上面的战略办法和工厂办法。

首要,战略办法中重要的Context人物在这儿边是没有的,没有Context,也就没有用到组合的办法,而是运用工厂替代了。

别的,这儿边的UserPayServiceStrategyFactory其实仅仅保护forget了一个Map,并供给了register和get办法罢了,而工厂办法其实是帮助创立目标的,这儿并没有用到。

所以,读者不用纠结于究竟是不是真的用了战略办法和工厂办法。并且,这儿边也再扩展一句,所谓的GOF 23种规划办法,不管从哪本书或许哪个博客看,都是简略的代码示例,可是咱们日常开发许多都是根据Spring等结构的,底子没办法直接用的。

所以,关于规划办法的学习,重要的是学习其思维,而不是代码完成!!!

假如读者们感兴趣,后续能够出更多的规划办法和Spring等结构结合运用的最佳实践。期望经过这样的文章,读者能够真实的在代码中运用上规划办法。


--------------------------------

原文我请重视大众号:hmcoding,更多精彩内容共享给咱们

声明感谢您对我们网站的认可,非常欢迎各位朋友分享本站内容到个人网站或者朋友圈,
转转请注明出处:http://lxcaopi.com/articles/1516.html
点赞 打赏

打赏方式:

支付宝扫一扫

微信扫一扫

扫一扫
QQ客服:111111111
工作日: 周一至周五
工作时间: 9:00-18:00