1.策略模式定義
策略模式(Strategy Pattern)是一種行為型設計模式,它定義了一組算法,將每個算法封裝起來,并使它們可以相互替換,從而讓算法的變化獨立于使用它的客戶(Client)。
換句話說, 策略模式讓一個類的行為或其算法可以在運行時更改,而不會影響使用該類的代碼。
UML圖:
2.策略模式舉例:
業務場景:需要實現一個商場收銀系統,有三種策略,
- 正常結賬
- 打折
- 滿減
實現業務功能如下:
2.1 代碼設計UML圖如下:
2.2 關鍵代碼:
CashContext代碼:和抽象工廠結合,減少耦合。之前客戶端需要了解CashContext和CashSuper兩個類,現在只需要了解CashContext一個類,封裝更好,耦合更小。
public class CashContext {private CashSuper cs; //聲明一個CashSuper對象//通過構造方法,傳入具體的收費策略public CashContext(int cashType){switch(cashType){case 1:this.cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;}}public double getResult(double price,int num){//根據收費策略的不同,獲得計算結果return this.cs.acceptCash(price,num);}
}
CashSuper:
public abstract class CashSuper {public abstract double acceptCash(double price,int num);
}
CashReturn:
public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利條件private double moneyReturn = 0d; //返利值//返利收費。初始化時需要輸入返利條件和返利值。//比如“滿300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//計算收費時,當達到返利條件,就原價減去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return result;}}
客戶端代碼:
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("策略模式和簡單工廠模式");System.out.println(); int discount = 0; //商品折扣模式(1.正常收費 2.打八折 3.打七折)double price = 0d; //商品單價int num = 0; //商品購買數量double totalPrices = 0d;//當前商品合計費用double total = 0d; //總計所有商品費用Scanner sc = new Scanner(System.in);do {System.out.println("請輸入商品折扣模式(1.正常收費 2.打八折 3.打七折 4.滿300送100):"); discount = Integer.parseInt(sc.nextLine());System.out.println("請輸入商品單價:"); price = Double.parseDouble(sc.nextLine());System.out.println("請輸入商品數量:"); num = Integer.parseInt(sc.nextLine());System.out.println(); if (price>0 && num>0){//根據用戶輸入,將對應的策略對象作為參數傳入CashContext對象中CashContext cc = new CashContext(discount);//通過Context的getResult方法的調用,可以得到收取費用的結果//讓具體算法與客戶進行了隔離totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println(); System.out.println("單價:"+ price + "元 數量:"+ num +" 合計:"+ totalPrices +"元"); System.out.println();System.out.println("總計:"+ total+"元"); System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}
具體運行結果如下:
3.策略模式優缺點
? 優點
- 符合開閉原則(Open-Closed Principle):可以新增新的策略,而不影響已有代碼。
- 避免冗長的 if-else 語句:如果不使用策略模式,可能會有大量 if-else 邏輯判斷。
- 支持動態切換:可以在運行時自由更換不同的算法,而不修改原有代碼。
- 代碼更符合SOLID原則
設計原則 | 策略模式如何符合 |
---|---|
單一職責原則(SRP) | 每個 Strategy 只負責一個算法,職責清晰。 |
開閉原則(OCP) | 可以新增策略,而不修改原代碼。 |
依賴倒置原則(DIP) | Context 依賴于 Strategy 接口,而不是具體實現。 |
? 缺點
- 增加了代碼復雜度:每個策略都需要定義一個類,當策略過多時,會導致類爆炸。
- 客戶端需要了解不同策略:調用方需要知道有哪些可用策略,才能正確選擇。
4.策略模式的應用場景
? (1) 算法的可替換性
計算稅收(不同國家稅率)
支付方式(微信支付、支付寶、銀行卡)
? (2) 處理不同格式的文件
解析 JSON、XML、CSV 文件時,使用不同的解析策略。
? (3) AI/機器學習中的優化策略
訓練模型時,可以使用不同的優化算法(SGD、Adam、RMSprop)。
5.策略模式 vs 其他模式
設計模式 | 作用 | 適用場景 |
---|---|---|
策略模式 | 允許在運行時更換不同算法 | 當有多種算法可選,且希望避免 if-else 邏輯。 |
狀態模式 | 允許對象在不同狀態下表現出不同行為 | 對象的行為依賴于狀態變化,例如訂單狀態。 |
工廠模式 | 負責創建對象,但不指定其具體實現 | 需要動態創建不同策略對象時,可結合策略模式使用。 |
6.總結
策略模式核心思想: 定義一組算法,讓它們可以互相替換,而不會影響客戶端代碼。
適用于: 需要多個可替換算法,并希望避免 if-else 邏輯的場景。
優點: 符合開閉原則,可動態切換策略,避免冗長 if-else
缺點: 可能會增加類的數量,使代碼更復雜。
7.參考引用
- https://juejin.cn/post/7485322373614813220