策略模式
策略模式(Strategy Pattern)是一種行為型設計模式,核心思想是將一組算法封裝成獨立對象,使它們可以相互替換,從而讓算法的變化獨立于使用它的客戶端。這類似于游戲中的技能切換——玩家根據戰況選擇不同技能(火球術、冰箭術),而角色的攻擊邏輯無需修改。
一、通俗理解
以商場促銷為例:
- 傳統方式:用
if-else
判斷促銷類型(滿減、折扣、積分),導致代碼臃腫且難以擴展新促銷策略。 - 策略模式:
- 促銷策略接口:定義統一的優惠計算接口(如
calculate()
)。 - 具體策略類:滿減策略、折扣策略等各自實現算法。
- 訂單上下文:持有當前策略對象,調用時動態執行對應算法。
當新增“雙倍積分”促銷時,只需添加新策略類,無需修改現有代碼。
- 促銷策略接口:定義統一的優惠計算接口(如
二、模式結構
- 抽象策略(Strategy):定義算法的公共接口(如
execute()
)。 - 具體策略(ConcreteStrategy):實現具體算法(如加法、折扣)。
- 上下文(Context):維護策略對象引用,提供切換和執行接口。
三、適用場景
- 動態算法切換:如支付方式(微信、支付寶)、排序算法(快排、歸并)。
- 消除條件分支:替代大量
if-else
或switch-case
語句。 - 算法復用與擴展:需要獨立管理多種算法變體時。
四、優缺點分析
優點 | 缺點 |
---|---|
1. 靈活擴展:新增策略無需修改上下文 | 1. 類數量膨脹:每個策略需獨立類 |
2. 消除條件判斷:代碼更簡潔易維護 | 2. 客戶端需感知策略存在 |
3. 符合開閉原則:算法與使用解耦 | 3. 性能開銷:頻繁切換可能影響效率 |
五、代碼實現
1. C++ 示例(計算器策略)
#include <iostream> // 抽象策略:運算接口
class Strategy {
public: virtual int execute(int a, int b) = 0; virtual ~Strategy() = default;
}; // 具體策略:加法
class AddStrategy : public Strategy {
public: int execute(int a, int b) override { return a + b; }
}; // 上下文:計算器
class Calculator { Strategy* strategy;
public: void setStrategy(Strategy* s) { strategy = s; } int calculate(int a, int b) { return strategy->execute(a, b); }
}; int main() { Calculator calc; calc.setStrategy(new AddStrategy()); std::cout << "10 + 5 = " << calc.calculate(10, 5) << std::endl; // 輸出15 // 切換策略示例:calc.setStrategy(new SubtractStrategy()); return 0;
}
解析:
- 通過
setStrategy()
動態更換加減乘除算法。
2. Python 示例(促銷策略)
from abc import ABC, abstractmethod class PromotionStrategy(ABC): @abstractmethod def calculate(self, price: float) -> float: pass class FullReductionStrategy(PromotionStrategy): # 滿減策略 def calculate(self, price): return price - 20 if price >= 100 else price class DiscountStrategy(PromotionStrategy): # 折扣策略 def calculate(self, price): return price * 0.8 class Order: def __init__(self, strategy: PromotionStrategy): self.strategy = strategy def checkout(self, price): return self.strategy.calculate(price) # 客戶端
order = Order(FullReductionStrategy())
print(f"滿減后價格:{order.checkout(150)}") # 輸出130.0
特點:
- Python支持鴨子類型,無需嚴格接口繼承。
3. Java 示例(支付策略 + 工廠模式)
// 策略接口
interface PaymentStrategy { void pay(double amount);
} // 具體策略:微信支付
class WechatPay implements PaymentStrategy { public void pay(double amount) { System.out.printf("微信支付:%.2f元\n", amount); }
} // 策略工廠(管理實例)
class PaymentFactory { private static final Map<String, PaymentStrategy> strategies = new HashMap<>(); static { strategies.put("wechat", new WechatPay()); strategies.put("alipay", new Alipay()); } public static PaymentStrategy getStrategy(String key) { return strategies.getOrDefault(key, new DefaultPay()); }
} // 上下文
class ShoppingCart { private PaymentStrategy strategy; public void setStrategy(String key) { this.strategy = PaymentFactory.getStrategy(key); } public void checkout(double amount) { strategy.pay(amount); }
} // 測試
ShoppingCart cart = new ShoppingCart();
cart.setStrategy("wechat");
cart.checkout(99.9); // 輸出:微信支付:99.90元
優化點:
- 工廠模式集中管理策略實例,避免重復創建。
六、總結與擴展
策略模式通過算法封裝和動態切換實現了高擴展性,特別適合以下場景:
- 電商促銷:不同優惠規則獨立管理。
- 游戲技能系統:角色動態切換攻擊策略。
- 數據解析:支持JSON、XML等多種格式解析器。
擴展技巧:
- 結合享元模式復用無狀態策略對象(如線程安全的計算策略)。
- 使用Lambda表達式(Java/Python)簡化小型策略類的定義。
- 參考資料
- 策略模式基礎結構與角色定義
- 三國錦囊案例與設計思想
- C++策略模式與對象生命周期管理
- Python策略模式與動態語言特性
- Java策略模式與線程安全實踐