策略模式

定義

策略(Strategy)模式定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶,通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不同的對象對這些算法進行實現和管理。

策略模式屬於對象行爲型模式。


要點

優點:

  1. 多重條件語句不易維護,而使用策略模式可以避免使用多重條件語句。
  2. 提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類裏面,從而避免重複的代碼。
  3. 可以提供相同行爲的不同實現,客戶可以根據不同時間或空間要求選擇不同的。
  4. 提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
  5. 把算法的使用放到環境類中,而算法的實現移到具體策略類中,實現了二者的分離。

缺點:

  1. 客戶端必須理解所有策略算法的區別,以便適時選擇恰當的算法類。
  2. 策略模式造成很多的策略類。

主要角色:
抽象策略(Strategy):定義了一個公共接口,各種不同的算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實現。
具體策略(Concrete Strategy):實現了抽象策略定義的接口,提供具體的算法實現。
環境(Context):持有一個策略類的引用,最終給客戶端調用。

在這裏插入圖片描述

場景

某商場舉辦回饋會員活動,促銷購物優惠規則如下:

  1. 對初級會員提供10%的促銷折扣。
  2. 對中級會員提供20%的促銷折扣。
  3. 對高級會員提供30%的促銷折扣。

實現

MemberStrategy

/**
 * 會員優惠策略
 */
public interface MemberStrategy {

    /**
     * 根據會員等級計算最終價格
     */
    double discountPrice(double originalPrice);

}

PrimaryMemberStrategy

/**
 * 初級會員策略
 */
public class PrimaryMemberStrategy implements MemberStrategy{

    @Override
    public double discountPrice(double originalPrice) {
        System.out.println("您是初級會員,享受10%的購物折扣");
        return originalPrice * 0.9;
    }

}

IntermediateMemberStrategy

/**
 * 中級會員策略
 */
public class IntermediateMemberStrategy implements MemberStrategy {

    @Override
    public double discountPrice(double originalPrice) {
        System.out.println("您是中級會員,享受20%的購物折扣");
        return originalPrice * 0.8;
    }

}

AdvancedMemberStrategy

/**
 * 高級會員策略
 */
public class AdvancedMemberStrategy implements MemberStrategy {

    @Override
    public double discountPrice(double originalPrice) {
        System.out.println("您是高級會員,享受30%的購物折扣");
        return originalPrice * 0.7;
    }

}

ShoppingContext

/**
 * 購物環境類
 */
public class ShoppingContext {

    /**
     * 持有一個具體的策略對象
     */
    private MemberStrategy strategy;

    public ShoppingContext(MemberStrategy strategy){
        this.strategy = strategy;
    }

    /**
     * 計算商品的價格
     */
    public void handle(double originalPrice){
        double discountPrice = this.strategy.discountPrice(originalPrice);
        System.out.println(String.format("您的購物商品原價爲:%s元,優惠後您需要支付%s元", originalPrice, discountPrice));
    }

    public void setStrategy(MemberStrategy strategy) {
        this.strategy = strategy;
    }
    
}

Client

public class Client {

    public static void main(String[] args) {
        ShoppingContext shoppingContext = new ShoppingContext(new PrimaryMemberStrategy());
        shoppingContext.handle(1000.0);

        shoppingContext.setStrategy(new AdvancedMemberStrategy());
        shoppingContext.handle(1000.0);
    }

}

-------------------輸出--------------------
您是初級會員,享受10%的購物折扣
您的購物商品原價爲:1000.0元,優惠後您需要支付900.0元

您是高級會員,享受30%的購物折扣
您的購物商品原價爲:1000.0元,優惠後您需要支付700.0

源碼

Click here


總結

策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活,具有更好的維護性和擴展性。

適用場景:

  1. 一個系統需要動態地在幾種算法中選擇一種時,可將每個算法封裝到策略類中。
  2. 一個類定義了多種行爲,並且這些行爲在這個類的操作中以多個條件語句的形式出現,可將每個條件分支移入它們各自的策略類中以代替這些條件語句。
  3. 系統中各算法彼此完全獨立,且要求對客戶隱藏具體算法的實現細節時。
  4. 系統要求使用算法的客戶不應該知道其操作的數據時,可使用策略模式來隱藏與算法相關的數據結構。
  5. 多個類只區別在表現行爲不同,可以使用策略模式,在運行時動態選擇具體要執行的行爲。

JDK中的 ThreadPoolExecutor 中適用策略模式,有四種拒絕策略。

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