营销项目策略+模板方法+工厂运用

在之前做的营销项目中,优惠券有满减券和折扣券类型(后面会增加类型),这两种类型的计算规则是不一样的,满减是用减法,折扣是用%。如果用if(满减){}else if(折扣){}来处理,那么就显得很low
这种场景使用了策略+模板方法+工厂。策略就是替代了 if else ,模板方法是将满减券和折扣券都需要用到的逻辑写到抽象父类上让这两种类型继承,就可以复用方法,工厂主要是通过spring的ioc注入来实现。
直接代码展示

首先定义优惠券计算的接口

public interface ICouponCalculate {
    /**
     * 优惠计算方法定义
     */
    CalculateResultDTO calculate(RulesExecuteReqDTO rulesExecuteReqDTO);

    /**
     * 计算规则对应的枚举
     *
     * @return
     */
    MarketingTypeEnum calculateType();

  // 这里主要是当获取不到对应优惠券类型的策略类,就默认获取这个类来报错提示
    ICouponCalculate DEFAULT_IMPLEMENT = new ICouponCalculate() {

        @Override
        public CalculateResultDTO calculate(RulesExecuteReqDTO rulesExecuteReqDTO) {
            throw new UnsupportedOperationException();
        }

        @Override
        public MarketingTypeEnum calculateType() {
            throw new UnsupportedOperationException();
        }
    };

}

然后定义策略类的优惠券计算的抽象父类 实现优惠券计算的接口

public abstract class CouponCalculateAbstract implements ICouponCalculate {
    public final static double PERCENT = 0.01;

    public final static double MIN_KHR = 1;
    public final static double MIN_USD = 0.01;
// 美元的优惠金额必须满0.01元,不然不能使用这张优惠券,HKR必需满1元
// 这个方法满减券和折扣券都需要用到,所以写到父类上
    protected boolean isDiscount(CurrencyTypeEnum currencyType, int calculateKHR, double calculateUSD) {
        if (currencyType.equals(CurrencyTypeEnum.KHR)) {
            if (calculateKHR < MIN_KHR) {
                // KHR少于1元,不返现
                log.info("KHR优惠金额小于1");
                return false;
            }
        }
        if (currencyType.equals(CurrencyTypeEnum.USD)) {
            if (calculateUSD < MIN_USD) {
                // USD少于0.01元,不返现
                log.info("USD优惠金额小于0.01");
                return false;
            }
        }
        return true;
    }

然后写具体类型的策略类,继承抽象父类
满减策略类

@Component
public class FullCouponCalculateStrategy extends CouponCalculateAbstract {
    @Override
    public CalculateResultDTO calculate(RulesExecuteReqDTO rulesExecuteReqDTO) {
        log.info("满减优惠券计算");
      ......
        return calculateResultDTO;
    }
    @Override
    public MarketingTypeEnum calculateType() {
        return MarketingTypeEnum.FULL_COUPON;
    }
}

折扣策略类

@Component
public class DiscountCouponCalculateStrategy extends CouponCalculateAbstract {
    @Override
    public CalculateResultDTO calculate(RulesExecuteReqDTO rulesExecuteReqDTO) {
        log.info("折扣优惠券计算");
       业务代码省略......
        return calculateResultDTO;
    }

    @Override
    public MarketingTypeEnum calculateType() {
        return MarketingTypeEnum.DISCOUNT_COUPON;
    }
}

运行策略的Context类,首先通过构造方法IOC注入方式获取到所有的优惠券计算实现类,然后封装map中 key对应类型的枚举,value为具体实现类。这个map相当于策略类的工厂

@Component
public class CouponCalculateStrategyContext {
    // 定义map,优惠券类型对应计算类
    Map<MarketingTypeEnum, ICouponCalculate> calculateMap = new EnumMap<>(MarketingTypeEnum.class);

    // 初始化calculateMap,将对应的关系存到calculateMap中
    @Autowired
    public CouponCalculateStrategyContext(final Map<String, ICouponCalculate> instanceMap) {
        // 将Map<String, ICalculate> calculateInstance传成对应计算规则的枚举Map<RegisteredCashBackTypeEnum, ICalculate>
        Map<MarketingTypeEnum, ICouponCalculate> collect = instanceMap.values().stream()
                .filter(iCouponCalculate -> iCouponCalculate.calculateType() != null)
                .collect(Collectors.toMap(ICouponCalculate::calculateType, iCouponCalculate -> iCouponCalculate));
        calculateMap.putAll(collect);
    }

    // 执行策略方法
    public CalculateResultDTO doCouponCalculate(MarketingTypeEnum marketingType, RulesExecuteReqDTO rulesExecuteReqDTO) {
        ICouponCalculate couponCalculate = calculateMap.getOrDefault(marketingType, DEFAULT_IMPLEMENT);
        return couponCalculate.calculate(rulesExecuteReqDTO);
    }

}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 写在前面: 最近工作压力不小,不想输得很惨就必须自己push自己。继续钻研促销系统设计 不定期摘读一些对自己有用的...
    Heenor阅读 4,837评论 2 11
  • 帮朋友转发。 上宁健康双十一限时折扣,诚招代理.“解卡—菊粉”一款绝对绿色的健康食品,让健康伴您肠在![勾引][勾...
    萌妹纸d霸气范er阅读 182评论 0 0
  • 阳光明媚的日子, 是我们所期待的, 别让任何人影响到你的内心, 而让...
    hzk思柚阅读 166评论 0 0
  • 早晨醒来,揉揉双眼尽力睁开 又得为一日三餐思虑 又得为一天生计奔忙 连轴的日子,如同拉磨的牛 蒙上双眼循环不停 喜...
    瀚海戏墨阅读 198评论 0 4