Loading...
墨滴

故事与你

2021/06/09  阅读:34  主题:科技蓝

设计模式之策略模式

策略

策略,即是我们在生活中面对一件事的多种做法,比如我要去北京, 通常可以做火车,高铁,拼车等,或者自驾也可以,一个目标多种实现,放到业务中可能就有很多分支,如何将这些分支实例化,拒绝if..else,这次带了干货哈哈😄

最近更新的文章类型比较杂,其实就是想拓宽一下自己的知识体系,作为设计模式,也是我们作为项目研发人员在考虑产品迭代的过程中就需要想到的,比如现在支付方式,你开一个文具店,支付的场景分为现金,银行卡,以及扫码支付,扫码有可以分为微信,支付宝,银联等支付方式,现在有比如新兴的优惠券满减,活动,以及免单抽奖等,这些都需要动态的记录支付方式,一来二去的,这个支付业务的树就越来越丰富, 难道我们就一直if/else下去吗?

不,我们不能够

策略模式

策略,即是战略,为了实现某一个场景下,抽象出的多种实现方式,这些方式的控制与实现就是我们今天要聊的策略模式。

可能没有具体的场景,理解起来比较困难,比如你自己的身份,面对不同的人,你的身份也会随之变化,称呼也会变化;

比如面对我的爷爷, 我会说爷爷好,身体怎么样了。 对我的妈妈, 老妈好啊,最近家里可好, 。。。。。

针对的对象不同,结果也是不同的;

这次我们就准备开始定制场景,开干;

场景:

你在京东买东西,一般可以商品的优惠,优惠类型分为多种,可以分为满减(满200减20),直减,折扣劵(8.8),N元购,类型, 其中优惠类型就可以作为我们实现优惠的多种方式,

刚毕业的写法:

public class CouponDiscountService {

    public double discountAmount(int type, double typeContent, double skuPrice, double typeExt) {
        // 1. 直减券
        if (1 == type) {
            return skuPrice - typeContent;
        }
        // 2. 满减券
        if (2 == type) {
            if (skuPrice < typeExt) return skuPrice;
            return skuPrice - typeContent;
        }
        // 3. 折扣券
        if (3 == type) {
            return skuPrice * typeContent;
        }
        // 4. n元购
        if (4 == type) {
            return typeContent;
        }
        return 0D;
    }

}

此方法是我们常用的匹配方法,用于做小范围的匹配,规定枚举值进行分类,然后分别实现,但是这样代码的耦合性,和可维护性会大大下降,可读性也越来越差,

策略模式教你怎么玩

定制具体的优惠方法,然后开展实现类,实现类就是多种策略的实现,其中我们要用到泛型方法用作公共接口的入参表示;

public interface ICouponDiscount<T> {

    /**
     * 优惠券金额计算
     * @param couponInfo 券折扣信息;直减、满减、折扣、N元购
     * @param skuPrice   sku金额
     * @return           优惠后金额
     */
    BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice);

}

定制化的接口,分为 标准的优惠类型T ,以及商品的原价,返回商品优惠后的价格,

优惠类型实现

满减

通常说的满减,当满金额之后,减去加个,如果不符合会返回原来的价格,(满200减20)

public class MJCouponDiscount implements ICouponDiscount<Map<String,String>>  {

    /**
     * 满减计算
     * 1. 判断满足x元后-n元,否则不减
     * 2. 最低支付金额1元
     */
    public BigDecimal discountAmount(Map<String,String> couponInfo, BigDecimal skuPrice) {
    
    
    //当前的设定价格是满200减20
        String x = couponInfo.get("x");
        String o = couponInfo.get("o");

        // 小于商品金额条件的,直接返回商品原价
        if (skuPrice.compareTo(new BigDecimal(x)) < 0) return skuPrice;
        // 减去优惠金额判断
        BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(o));
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE;

        return discountAmount;
    }
}

很多人对compareTo这个接口可能不太了解,我这里做个简单的demo

public class Test {
 
    public static void main(String args[]) {
        String str1 = "Strings";
        String str2 = "Strings";
        String str3 = "Strings123";
 
        int result = str1.compareTo( str2 );
        System.out.println(result);
         //0
        result = str2.compareTo( str3 );
        System.out.println(result);
        //-3
        result = str3.compareTo( str1 );
        System.out.println(result);
        //3
    }
}

compareTo主要用于对象之间的比较,

  • 如果参数字符串等于此字符串,则返回值 0;
  • 如果此字符串小于字符串参数,则返回一个小于 0 的值;
  • 如果此字符串大于字符串参数,则返回一个大于 0 的值。

直减

ublic class ZJCouponDiscount implements ICouponDiscount<Double>  {

    /**
     * 直减计算
     * 1. 使用商品价格减去优惠价格
     * 2. 最低支付金额1元
     */
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(couponInfo));
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE;
        return discountAmount;
    }

}

####折扣劵

public class ZKCouponDiscount implements ICouponDiscount<Double> {


    /**
     * 折扣计算
     * 1. 使用商品价格乘以折扣比例,为最后支付金额
     * 2. 保留两位小数
     * 3. 最低支付金额1元
     */
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        BigDecimal discountAmount = skuPrice.multiply(new BigDecimal(couponInfo)).setScale(2, BigDecimal.ROUND_HALF_UP);
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE;
        return discountAmount;
    }

}

N元购

public class NYGCouponDiscount implements ICouponDiscount<Double> {

    /**
     * n元购购买
     * 1. 无论原价多少钱都固定金额购买
     */
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        return new BigDecimal(couponInfo);
    }

}

总结

对于策略模式,主要是根据多种实现方式抽象出标准的接口,利用接口与实现类的关系,多种实现,不再依赖于单纯的if。。else的单值匹配,完成任务,上方的代码来自于我今晚刚到的新货,小傅哥的《重学Java设计模式》,感觉这个优惠券的类型对标策略模式更加生动形象,其实这只是简单的让你理解策略模式,在真正的项目中,可能是工厂加上代理加上策略模式来实现AOP切面的场景,

一切技术需要有实际业务的支撑才能发挥价值,所以都要考虑具体的场景去实现,好了,今天的分享就到这里了,

我是卢卡,要早睡点了,昨晚晚睡,身体有点扛不住,大家看完记得点赞 加评论哦,晚安好梦。

故事与你

2021/06/09  阅读:34  主题:科技蓝

作者介绍

故事与你