前言
在开发电商折扣模块的时候经常会碰到各种优惠规则,那么就会碰到很多条件判断,冗余各种if-else的代码使得维护困难,此时就可以用策略模式来解决,替代大量的冗余判断条件代码,精简代码结构。
策略模式是一种行为模式,也是替代大量ifelse的利器。它所能帮你解决的是场景,一般是具有同类可替代的行为逻辑算法场景。比如;不同类型的交易方式(信用卡、支付宝、微信)、生成唯一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法)等,都可以使用策略模式进行行为包装,供给外部使用。
1、定义优惠券折扣接口类
/**
* @describe:优惠卷折扣计算接口
* 1. 直减卷
* 2. 满减卷
* 3. 折扣卷
* 4. N元购
*/
public interface ICouponDiscount<T> {
/**
*
* @param couponInfo 券折扣信息;直减、满减、折扣、N元购
* @param skuPrice 商品价格
* @return 优惠后金额
*/
BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice);
}
2、实现折扣接口
-
满减规则
/**
* @describe:满减
*/
public class MJCouponDiscount implements ICouponDiscount<Map<String,String>> {
/**
* 满减计算
*1. 判断满足x元后-n元,否则不减
*2. 最低支付金额1元
* @param couponInfo
* @param skuPrice
* @return
*/
@Override
public BigDecimal discountAmount(Map<String, String> couponInfo, BigDecimal skuPrice) {
//满100
String x = couponInfo.get("x");
//减10
String y = couponInfo.get("y");
//小于商品金额条件,直接返回
if(skuPrice.compareTo(new BigDecimal(x)) < 0){
return skuPrice;
}
//减去优惠金额判断
BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(y));
//满减后价格小于等于0,那么支付最低1元
if(discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE;
return discountAmount;
}
}
-
N元购规则
/**
* @describe:N元购
*/
public class NYGCouponDiscount implements ICouponDiscount<Double> {
/**
* n元购购买
* 1. 无论原价多少钱都固定金额购买
*/
@Override
public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
return new BigDecimal(couponInfo);
}
}
-
折扣规则
/**
* @describe:
*/
public class ZKCouponDiscount implements ICouponDiscount<Double> {
/**
* 折扣计算
* 1. 使用商品价格乘以折扣比例,为最后支付金额
* 2. 保留两位小数
* 3. 最低支付金额1元
*/
@Override
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;
}
}
-
直接减规则
/**
* @describe:直减
*/
public class ZjCouponDiscount implements ICouponDiscount<Double> {
/**
* 直减计算
* 1. 使用商品价格减去优惠价格
* 2. 最低支付金额1元
*/
@Override
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;
}
}
3、策略上下文
定义策略的上下文,策略控制器,通过控制器调用不同的优惠策略
/**
* @describe:策略控制器
*/
public class Context <T>{
private ICouponDiscount<T> couponDiscount;
public Context(ICouponDiscount<T> couponDiscount) {
this.couponDiscount = couponDiscount;
}
public BigDecimal discountAmount(T couponInfo,BigDecimal skuPrice){
return couponDiscount.discountAmount(couponInfo,skuPrice);
}
}
4、编写测试类(调用方法)
调用控制器,走不同的折扣规则
@Test
public void test(){
// 直减;100-10,商品100元
Context<Double> context = new Context<Double>(new ZJCouponDiscount());
BigDecimal discountAmount = context.discountAmount(10D, new BigDecimal(100));
logger.info("测试结果:直减优惠后金额 {}", discountAmount);
}