策略模式(Strategy Pattern)

介紹

策略模式(Strategy Pattern)是指定義了算法家族、分別封裝起來,讓它們之間可以互 相替換,此模式讓算法的變化不會影響到使用算法的用戶。

優點

1、策略模式符合開閉原則。

2、避免使用多重條件轉移語句,如 if...else...語句、switch 語句

3、使用策略模式可以提高算法的保密性和安全性。

缺點

1、客戶端必須知道所有的策略,並且自行決定使用哪一個策略類。

2、代碼中會產生非常多策略類,增加維護難度。

使用場景

1、假如系統中有很多類,而他們的區別僅僅在於他們的行爲不同。

2、一個系統需要動態地在幾種算法中選擇一種。

使用建議

實際的開發中使用的比較多,多重if...else...可以考慮使用這種方式。

具體實現

(實例一)選擇不同的支付方式:

類圖

代碼

package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class PayState {
    private int code;
    private Object data;
    private String msg;

    public PayState(int code, String msg,Object data ) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "支付狀態:[" +code+"]" + "支付金額:" + data + "響應信息:" + msg ;
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

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 PayState pay(){
        return pay(PayStrategyFactory.PayTypeEnum.Default.getType());
    }

    public PayState pay(String payTypeKey){
        Payment payment=PayStrategyFactory.getPayType(payTypeKey);
        System.out.println("歡迎使用  " + payment.getName() + "  支付");
        System.out.println("本次交易金額爲:"+amount+",開始扣款...");
        return payment.pay(uid,amount);
    }

}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

/**
 * 支付渠道
 */

public abstract class Payment {
    /**
     * 支付方式
     * @return
     */
    public abstract String getName();

    /**
     * 查詢餘額
     * @param uid
     * @return
     */
    public abstract double queryBalance(String uid);

    public PayState pay(String uid,double amount){
        if(queryBalance(uid)<amount){
            return new PayState(500,"支付失敗","餘額不足");
        }
        return new PayState(200,"支付成功","支付金額:"+amount);
    }

}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class AliPay extends Payment {
    @Override
    public String getName() {
        return "支付寶";
    }

    @Override
    public double queryBalance(String uid) {
        return 900;
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class JDPay extends Payment {
    @Override
    public String getName() {
        return "京東百度";
    }

    @Override
    public double queryBalance(String uid) {
        return 100;
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class UnionPay extends Payment {
    @Override
    public String getName() {
        return "銀聯支付";
    }

    @Override
    public double queryBalance(String uid) {
        return 120;
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class WechatPay extends Payment{
    @Override
    public String getName() {
        return "微信支付";
    }

    @Override
    public double queryBalance(String uid) {
        return 256;
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

import java.util.HashMap;
import java.util.Map;

public class PayStrategyFactory {

    private PayStrategyFactory() {}

    private static Map <String, Payment> paymentMap=new HashMap <>();
    static {
        paymentMap.put(PayTypeKey.Default,new AliPay());
        paymentMap.put(PayTypeKey.AliPay,new AliPay());
        paymentMap.put(PayTypeKey.JDPay,new JDPay());
        paymentMap.put(PayTypeKey.UnionPay,new UnionPay());
        paymentMap.put(PayTypeKey.WechatPay,new WechatPay());
    }

    public static Payment getPayType(String payType){
        Payment payment=paymentMap.get(payType);
        return null==payment?paymentMap.get("Default"):payment;
    }

    //通過接口實現----工廠類外部不方便使用
    private interface PayTypeKey{
        String AliPay="AliPay";
        String JDPay="JDPay";
        String UnionPay="UnionPay";
        String WechatPay="WechatPay";
        String Default="Default";
    }

    //通過枚舉實現----工廠類外部可方便的使用
    public enum PayTypeEnum{
        AliPay("AliPay"),
        JDPay("JDPay"),
        UnionPay("UnionPay"),
        WechatPay("WechatPay"),
        Default("Default"),
        ;
        private String type;

        PayTypeEnum(String type) {
            this.type = type;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.order_pay;

public class Test {
    public static void main(String[] args) {
        Order order=new Order("11","3210000005679000009",10);
        PayState state=order.pay(PayStrategyFactory.PayTypeEnum.JDPay.getType());
        System.out.println(state.toString());
    }
}

(實例二)不同的促銷打折方式:

類圖

代碼

package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

/**
 * 促銷抽象類
 */
public interface PromotionStrategy {
    void doPromotion();
}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

/**
 * 優惠券
 */
public class CouponStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("領取優惠券,下單享受優惠券折扣");
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

/**
 * 返現優惠
 */
public class CashBackStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("返現促銷,返回的金額轉到支付寶賬戶");
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

public class EmptyStrategy  implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("沒有促銷活動");
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

/**
 * 團購優惠
 */
public class GroupBuyStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("拼團,滿20人成團,全團享受團購價");
    }
}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

public class PromotionActivity {

    private PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }

    public void execute(){
        promotionStrategy.doPromotion();
    }

}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;

import java.util.HashMap;
import java.util.Map;

public class PromotionStrategyFactory {

    private PromotionStrategyFactory(){}

    private static final PromotionStrategy defaultPromotion=new EmptyStrategy();

    private static Map <String,PromotionStrategy> promotionStrategyMap=new HashMap<>();

    static {
        promotionStrategyMap.put(PromotionKey.CASHBACK,new CashBackStrategy());
        promotionStrategyMap.put(PromotionKey.COUPON,new CouponStrategy());
        promotionStrategyMap.put(PromotionKey.GROUTBUY,new GroupBuyStrategy());
    }

    public  static PromotionStrategy getPromotionStrategy(String promotionKey){
        PromotionStrategy promotionStrategy =promotionStrategyMap.get(promotionKey);
        return null==promotionStrategy?defaultPromotion:promotionStrategy;
    }

    private interface PromotionKey {
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUTBUY = "GROUTBUY";
    }

}
package com.knowledge.system.software_design_pattern.strategy_pattern.promotion;


public class Test {

    /*
    1.替換  if...else   switch...case
    2.一個系統需要動態的在幾種算法中選擇一種
    * */

    public static void main(String[] args) {
        System.out.println("策略模式測試");
        //第一種,完全和實際脫軌
/*
        PromotionActivity  activity=new PromotionActivity(new GroupBuyStrategy());
        PromotionActivity activity1=new PromotionActivity(new CashBackStrategy());
        activity.execute();
        activity1.execute();*/

        //第二種,冗餘了很多的if...else
/*      PromotionActivity activity=null;
        String promotionKey="COUPON";
        if(promotionKey.equals("COUPON")) {
            activity = new PromotionActivity(new CouponStrategy());
        }
        if(promotionKey.equals("CASHBACK")) {
            activity = new PromotionActivity(new CashBackStrategy());
        }
        if(promotionKey.equals("GROUPBUY")) {
            activity = new PromotionActivity(new GroupBuyStrategy());
        }
        activity.execute();*/

        //爲簡化代碼,引入單例模式與簡單工廠,繼續簡化代碼------史上最強策略模式
        String promotionKey = "CASHBACK";
        PromotionStrategy strategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey);
        strategy.doPromotion();
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章