策略模式+工厂模式 去除if-else

本文参考链接: https://juejin.im/post/5dad23685188251d2c4ea2b6

需求

1、多种会员优惠:超级会员折扣8折、普通会员折扣9折、普通用户没有折扣;
2、用户付款时,根据用户类型进行打折计算应付金额;
3、业务发展,新需求要求专属会员要在店铺下单金额大于30元时享受7折优惠;
4、新需求要求如果用户超级会员到期,并到期时间在一周内,对用户的单笔订单按照超级会员进行折扣,并在收银台强提心,引导用户再次开通会员,且只折扣一次。

未引入设计模式代码

public BigDecimal calPrice(BigDecimal orderPrice, String buyerType){

    if(用户是专属会员){
        if(订单金额大于30元){
            return 7折价格;
        }
    }
    
    if(用户是超级会员){
        return 8折价格;
    }
    
    if(用户是普通会员){
        if(该用户超级会员刚过期且尚未使用过临时折扣){
            临时折扣使用次数更新();
           return 8折价格;
        }
        return 9折价格;
    }

    return 原价;
}

引入策略模式

策略通用接口

public interface UserPayService{
    /**
     * 计算应付价格
     */
    public BigDicimal quote(BigDecimal orderPrice);
}

策略类

/**
 * 专属会员
 */
public class ParticularlyVipPayService implements UserPayService{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        if(消费金额大于30元){
            return 7折价格;
        }
    } 
}

/**
 * 超级会员
 */
public class SuperVipPayService implements UserPayService{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        return 8折价格;
    } 
}

/**
 * 普通会员
 */
public class VipPayService implements UserPayService{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        if(该用户超级会员刚过期且尚未使用过临时折扣){
            临时折扣使用次数更新();
           return 8折价格;
        }
        return 9折价格;
    } 
}

价格计算方法如下:

public BigDecimal calPrice(BigDecimal orderPrice, User user){

    String vipType = user.getVipType();
    
    if(vipType == 专属会员){
        //伪代码
        UserPayService strategy = Spring.getBean(ParticularlyVipPayService.class);
        return strategy.quote();
    }
    
    if (vipType == 超级会员) {
        UserPayService strategy = Spring.getBean(SuperVipPayService.class);
        return strategy.quote(orderPrice);
     }

     if (vipType == 普通会员) {
        UserPayService strategy = Spring.getBean(VipPayService.class);
        return strategy.quote(orderPrice);
     }
     return 原价;
}

上述内容可看出,引入策略模式代码维护性和可读性有所增强,但是并未消除if-else

引入工厂模式

工厂类

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 userPayService){
        Assert.notNull(userType, "userType can't be null");
        services.put(userType, userPayService);
    }
}

计算价格方法如下:

public BigDecimal calPrice(BigDecimal orderPrice, User user){
    String vipType = user.getVipType();
    UserPayService strategy = UserPayServiceStrategyFactory.getByUser(vipType);
    return strategy.quote(orderPrice);
}

又上述代码可见,引入工厂模式后,完全去除了代码中的if-else;

在Spring初始化时,需要将策略模式类都注册到工厂类中,将策略类进行改造,使用Spring的InitializingBean接口,在bean初始化后,执行afterPropertiesSet方法进行注册。代码如下:

/**
 * 专属会员
 */
public class ParticularlyVipPayService implements UserPayService, InitializingBean{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        if(消费金额大于30元){
            return 7折价格;
        }
    } 
    
    @Override
    public void afterPropertiesSet(){
        UserPayServiceStrategyFactory.register("ParticularlyVip", this);
    }
    
 /**
 * 超级会员
 */
public class SuperVipPayService implements UserPayService, InitializingBean{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        return 8折价格;
    } 
    
    @Override
    public void afterPropertiesSet(){
        UserPayServiceStrategyFactory.register("SuperVip", this);
    }
}

/**
 * 普通会员
 */
public class VipPayService implements UserPayService, InitializingBean{
    @Override
    public BigDicimal quote(BigDecimal orderPrice){
        if(该用户超级会员刚过期且尚未使用过临时折扣){
            临时折扣使用次数更新();
           return 8折价格;
        }
        return 9折价格;
    } 
    
    @Override
    public void afterPropertiesSet(){
        UserPayServiceStrategyFactory.register("Vip", this);
    }
}

你可能感兴趣的:(设计模式)