本文節選自《設計模式就該這樣學》
1 使用策略模式實作促銷優惠方案選擇
大家都知道,咕泡學院的架構師課程經常會有優惠活動,優惠策略有很多種可能,如領取優惠券抵扣、返現促銷、拼團優惠等,下面用代碼來模擬,首先創建一個促銷策略的抽象PromotionStrategy,
/**
* 促銷策略抽象
* Created by Tom.
*/
public interface IPromotionStrategy {
void doPromotion();
}
然后分別創建優惠券抵扣策略CouponStrategy類、返現促銷策略CashbackStrategy類、拼團優惠策略GroupbuyStrategy類和無優惠策略EmptyStrategy類,
CouponStrategy類的代碼如下,
public class CouponStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("使用優惠券抵扣");
}
}
CashbackStrategy類的代碼如下,
public class CashbackStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("返現,直接打款到支付寶賬號");
}
}
GroupbuyStrategy類的代碼如下,
public class GroupbuyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("5人成團,可以優惠");
}
}
EmptyStrategy類的代碼如下,
public class EmptyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("無優惠");
}
}
接著創建促銷活動方案PromotionActivity類,
public class PromotionActivity {
private IPromotionStrategy strategy;
public PromotionActivity(IPromotionStrategy strategy) {
this.strategy = strategy;
}
public void execute(){
strategy.doPromotion();
}
}
最后撰寫客戶端測驗代碼,
public static void main(String[] args) {
PromotionActivity activity618 = new PromotionActivity(new CouponStrategy());
PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy());
activity618.execute();
activity1111.execute();
}
此時,小伙伴們會發現,如果把上面這段客戶端測驗代碼放到實際的業務場景中,其實并不實用,因為我們做活動的時候往往要根據不同的需求對促銷策略進行動態選擇,并不會一次性執行多種優惠,所以代碼通常會這樣寫,
public static void main(String[] args) {
PromotionActivity promotionActivity = null;
String promotionKey = "COUPON";
if(StringUtils.equals(promotionKey,"COUPON")){
promotionActivity = new PromotionActivity(new CouponStrategy());
}else if(StringUtils.equals(promotionKey,"CASHBACK")){
promotionActivity = new PromotionActivity(new CashbackStrategy());
}//......
promotionActivity.execute();
}
這樣改造之后,代碼滿足了業務需求,客戶可根據自己的需求選擇不同的優惠策略,但是,經過一段時間的業務積累,促銷活動會越來越多,于是,程式員就開始經常加班,每次上活動之前都要通宵改代碼,而且要做重復測驗,判斷邏輯可能也會變得越來越復雜,此時,我們要思考代碼是否需要重構,回顧之前學過的設計模式,我們應該如何來優化這段代碼呢?其實,可以結合單例模式和簡單工廠模式,創建PromotionStrategyFactory類,
public class PromotionStrategyFacory {
private static Map<String,IPromotionStrategy> PROMOTIONS = new HashMap<String, IPromotionStrategy>();
static {
PROMOTIONS.put(PromotionKey.COUPON,new CouponStrategy());
PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTIONS.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
}
private static final IPromotionStrategy EMPTY = new EmptyStrategy();
private PromotionStrategyFacory(){}
public static IPromotionStrategy getPromotionStrategy(String promotionKey){
IPromotionStrategy strategy = PROMOTIONS.get(promotionKey);
return strategy == null ? EMPTY : strategy;
}
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
public static Set<String> getPromotionKeys(){
return PROMOTIONS.keySet();
}
}
這時候,客戶端測驗代碼如下,
public static void main(String[] args) {
PromotionStrategyFacory.getPromotionKeys();
String promotionKey = "COUPON";
IPromotionStrategy promotionStrategy = PromotionStrategyFacory.getPromotionStrategy (promotionKey);
promotionStrategy.doPromotion();
}
代碼優化之后,程式員的維護作業也變得輕松了,每次上新活動都不影響原來的代碼邏輯,
2 使用策略模式重構支付方式選擇場景
為了加深對策略模式的理解,我們再舉一個案例,相信小伙伴們都用過支付寶、微信支付、銀聯支付及京東白條,一個常見的應用場景就是大家在下單支付時會提示選擇支付方式,如果用戶未選,系統也會默認好推薦的支付方式進行結算,來看如下圖所示的類圖,我們用策略模式來模擬此業務場景,

首先創建Payment抽象類,定義支付規范和支付邏輯,代碼如下,
import com.tom.pattern.strategy.pay.PayState;
/**
* 支付渠道
* Created by Tom.
*/
public abstract class Payment {
public abstract String getName();
//通用邏輯被放到抽象類里實作
public MsgResult pay(String uid, double amount){
//余額是否足夠
if(queryBalance(uid) < amount){
return new MsgResult(500,"支付失敗","余額不足");
}
return new MsgResult(200,"支付成功","支付金額" + amount);
}
protected abstract double queryBalance(String uid);
}
然后分別創建具體的支付方式,支付寶AliPay類的代碼如下,
public class AliPay extends Payment {
public String getName() {
return "支付寶";
}
protected double queryBalance(String uid) {
return 900;
}
}
京東白條JDPay類的代碼如下,
public class JDPay extends Payment {
public String getName() {
return "京東白條";
}
protected double queryBalance(String uid) {
return 500;
}
}
微信支付WechatPay類的代碼如下,
public class WechatPay extends Payment {
public String getName() {
return "微信支付";
}
protected double queryBalance(String uid) {
return 263;
}
}
銀聯支付UnionPay類的代碼如下,
public class UnionPay extends Payment {
public String getName() {
return "銀聯支付";
}
protected double queryBalance(String uid) {
return 120;
}
}
接著創建支付狀態的包裝類MsgResult,
/**
* 支付完成以后的狀態
* Created by Tom.
*/
public class MsgResult {
private int code;
private Object data;
private String msg;
public MsgResult(int code, String msg, Object data) {
this.code = code;
this.data = https://www.cnblogs.com/gupaoedu-tom/p/data;
this.msg = msg;
}
@Override
public String toString() {
return"MsgResult{" +
"code=" + code +
", data="https://www.cnblogs.com/gupaoedu-tom/p/+ data +", msg='" + msg + '\'' +
'}';
}
}
創建支付策略管理類,
import java.util.HashMap;
import java.util.Map;
/**
* 支付策略管理
* Created by Tom.
*/
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String UNION_PAY = "UnionPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String,Payment> strategy = new HashMap<String,Payment>();
static {
strategy.put(ALI_PAY,new AliPay());
strategy.put(JD_PAY,new JDPay());
strategy.put(WECHAT_PAY,new WechatPay());
strategy.put(UNION_PAY,new UnionPay());
}
public static Payment get(String payKey){
if(!strategy.containsKey(payKey)){
return strategy.get(DEFAULT_PAY);
}
return strategy.get(payKey);
}
}
創建訂單Order類,
import com.tom.pattern.strategy.pay.payport.PayStrategy;
import com.tom.pattern.strategy.pay.payport.Payment;
/**
* Created by Tom.
*/
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public MsgResult pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("歡迎使用" + payment.getName());
System.out.println("本次交易金額為" + amount + ",開始扣款");
return payment.pay(uid,amount);
}
}
最后撰寫客戶端測驗代碼,
public static void main(String[] args) {
Order order = new Order("1","2020031401000323",324.5);
System.out.println(order.pay(PayStrategy.ALI_PAY));
}
運行結果如下圖所示,

通過常見的業務場景舉例,希望小伙伴們能夠更深刻地理解策略模式,
【推薦】Tom彈架構:收藏本文,相當于收藏一本“設計模式”的書
本文為“Tom彈架構”原創,轉載請注明出處,技術在于分享,我分享我快樂!
如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力,關注微信公眾號『 Tom彈架構 』可獲取更多技術干貨!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/349479.html
標籤:Java
上一篇:面試題系列:用了這么多年的 Java 泛型,我竟然只知道它的皮毛
下一篇:垃圾代碼和優質代碼的區別?
