源码地址:https://github.com/LiJiaHa0/pattern-strategy.git
策略模式是指定义了多个算法,称为算法家族,分别封装起来,让它们之间互相替换,此模式让算法的改变不会影响到使用算法的用户。
可以避免多重if…else和swich语句。
在我们平时生活中,比如在超市购物时,超市有时会根据我们的会员分打折你所需要购买的商品的总价,会员分满100分打9.9折,满200分打9.5折,300分打9折等等。还有我们买网上购物时,不管是京东还是淘宝,我们会领取优惠卷,你在这里买了总价格为50元时,减7元。满100元时减20元,满200元时减50元等等,这些我们在系统都使用了策略模式来进行算法区分,我们在提交订单时,只要有了优惠券,我们不管你怎么算,我只在乎我最后订单提交的总金额是不是跟我们领取的优惠卷优惠的价格相符。所以我们系统使用了不同的优惠卷算法才能使我们的订单正确获取到金额。
下面我们来用代码实现策略模式实现优惠卷减价格。
talk is cheap show me the code
首先我们来新建一个简易的订单信息对象。
/**
* @description: 我们的整个简易的订单信息
* @author: Jh Lee
* @create: 2019-03-16 16:49
**/
public class Order {
//订单提交人的id
private Long uId;
//订单编号
private String orderNo;
//我们在购物时的总购物价格
private double prices;
private String discountsKey;
public Order(Long uId, String orderNo, double prices, String discountsKey) {
this.uId = uId;
this.orderNo = orderNo;
this.prices = prices;
this.discountsKey = discountsKey;
}
public Long getuId() {
return uId;
}
public void setuId(Long uId) {
this.uId = uId;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public double getPrices() {
return prices;
}
public void setPrices(double prices) {
this.prices = prices;
}
public String getDiscountsKey() {
return discountsKey;
}
public void setDiscountsKey(String discountsKey) {
this.discountsKey = discountsKey;
}
}
新建我们通过我们优惠算法计算后的返回信息
/**
* @description: 记录我们计算使用优惠卷的后返回的信息
* @author: Jh Lee
* @create: 2019-03-16 17:16
**/
public class ResultMsg {
private int code;
private String msg;
private Object data;
public ResultMsg(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return "使用优惠券的结果为:" +
"成功编码:" + code +
", 信息:'" + msg + '\'' +
", 订单金额为:" + data +
'}';
}
}
然后我们新建一个优惠的抽象类,这个类中有一个我们对应个个不同算法的优惠方法。
/**
* @description: 定义一个总的活动抽象,在定义一个我们优惠活动的价格算法方法
* @author: Jh Lee
* @create: 2019-03-16 16:46
**/
public interface Discounts {
//传入我们的订单信息,计算我们总订单金额通过我们优惠算法后的所支付算法。
public ResultMsg calculate (Order order);
}
新建优惠卷一:满50减7,实现我们优惠活动的接口,编写我们满50-7的算法
/**
* @description: 优惠卷一,满50减7
* @author: Jh Lee
* @create: 2019-03-16 16:51
**/
public class FiftyMinusSeven implements Discounts {
//优惠使用价格门槛(需要总金额大于50时才能使用)
private static final double countPrices = 50.00;
//优惠的额度
private static final double limit = 7.00;
@Override
public ResultMsg calculate(Order order) {
//如果总金额大于50元时
if(order.getPrices() >= countPrices){
return new ResultMsg(200,"使用成功",order.getPrices() - limit);
}
return new ResultMsg(500,"使用失败",order.getPrices());
}
}
新建优惠卷二:满100-20,实现我们优惠活动的接口,编写我们满100-7的算法
/**
* @description: 优惠卷二,满一百减20
* @author: Jh Lee
* @create: 2019-03-16 17:25
**/
public class OneHundredMinusTwenty implements Discounts {
//优惠使用价格门槛(需要总金额大于100时才能使用)
private static final double countPrices = 100.00;
//优惠的额度
private static final double limit = 20.00;
@Override
public ResultMsg calculate(Order order) {
//如果总金额大于50元时
if(order.getPrices() >= countPrices){
return new ResultMsg(200,"使用成功",order.getPrices() - limit);
}
return new ResultMsg(500,"使用失败",order.getPrices());
}
}
新建优惠卷三:满200-50,实现我们优惠活动的接口,编写我们满200-50的算法
/**
* @description: 优惠卷三,满200一50
* @author: Jh Lee
* @create: 2019-03-16 17:32
**/
public class TwoHundredMinusFifty implements Discounts {
//优惠使用价格门槛(需要总金额大于200时才能使用)
private static final double countPrices = 200.00;
private static final double limit = 50.00;
@Override
public ResultMsg calculate(Order order) {
//如果总金额大于50元时
if(order.getPrices() >= countPrices){
return new ResultMsg(200,"使用成功",order.getPrices() - limit);
}
return new ResultMsg(500,"使用失败",order.getPrices());
}
}
新建我们默认的算法,无优惠
/**
* @description: 没有此优惠卷
* @author: Jh Lee
* @create: 2019-03-16 17:51
**/
public class NoneDiscount implements Discounts {
@Override
public ResultMsg calculate(Order order) {
return new ResultMsg(500,"暂无此优惠卷",order.getPrices());
}
}
接下来我们就要通过订单中所拥有的优惠卷key来进行判断具体使用哪一个优惠卷算法来进行优惠了。
通过我们一个简单工厂来通过优惠卷的key来进行获取具体优惠卷的算法类
/**
* @description: 通过我们的简单工厂模式,把我们全部优惠卷注入
* @author: Jh Lee
* @create: 2019-03-16 17:38
**/
public class DiscountsFactory {
//满五十减七
public static final String FIFTY_MINUS_SEVER = "fiftyMinusSever";
//满一百减
public static final String ONE_HUNDRED_MINUS_TWENTY = "oneHundredMinusTwenty";
//满两百减五十
public static final String TWO_HUNDRED_MINUS_FIFTY = "twoHundredMinusFifty";
//简单工厂的工厂容器
private static Map<String,Discounts> discountsFactory = new HashMap<String,Discounts>();
//通过静态代理块的类加载顺序来实例化工厂容器
static{
discountsFactory.put(FIFTY_MINUS_SEVER,new FiftyMinusSeven());
discountsFactory.put(ONE_HUNDRED_MINUS_TWENTY,new OneHundredMinusTwenty());
discountsFactory.put(TWO_HUNDRED_MINUS_FIFTY,new TwoHundredMinusFifty());
}
//通过优惠卷的key来判断是否存在我们的优惠卷
public static Discounts getDiscounts(String key){
if(discountsFactory.containsKey(key)){
return discountsFactory.get(key);
}
return new NoneDiscount();
}
}
可以看到,我们工厂通过一个简易的map容器(当然这里我们这里的容器还可以有更多选择,列表我们有一个优惠卷的数据表,专门用来存放我们对应的优惠卷集合)来存取我们系统中所用的几种优惠卷算法,然后通过我们的几个算法的静态属性来当作key,相对应的优惠卷算法来当value,然后用我们的静态方法块来进行容器的初始化(不知道静态方块块的可以先去了解一下类的加载顺序),然后通过我们的getDiscounts方法来进行相对应的优惠卷算法的获取。如果在之前,我们肯定是不断使用if…else if …else…if …else来进行判断了,现在我们策略模式则避免了这一操作。
接下来就是我们如果通过订单来进行对应的算法获取优惠的信息了。
新建一个使用优惠卷的类
/**
* @description: 通过我们的订单信息来使用我们的优惠卷算法
* @author: Jh Lee
* @create: 2019-03-16 17:34
**/
public class DiscountsUse {
//优惠卷的使用方法,通过我们的优惠卷工厂来获取我们的具体的优惠卷使用算法
public ResultMsg useCoupons(Order order){
return DiscountsFactory.getDiscounts(order.getDiscountsKey()).calculate(order);
}
}
可以看到,我们在userCoupons方法中传入一个订单,然后通过订单中的优惠卷id我们就可以返回不同的算法结果了。
测试一下
我们传入一个50元的订单,传入使用我们满50-7的优惠卷key
结果:
在传入一个101元的订单,传入我们满100-20的优惠卷key
结果:
然后传入我们250.13元的订单,传入我们满200-50的优惠卷key
结果: