策略
策略,即是我们在生活中面对一件事的多种做法,比如我要去北京,通常可以做火车,高铁,拼车等,或者自驾也可以,一个目标多种实现,放到业务中可能就有很多分支,如何将这些分支实例化,拒绝 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 主要用于对象之间的比较,
直减
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 切面的场景,
一切技术需要有实际业务的支撑才能发挥价值,所以都要考虑具体的场景去实现,好了,今天的分享就到这里了,
我是卢卡,要早睡点了,大家看完记得点赞 加评论哦,晚安好梦。
评论