核心思想
策略模式是一種行為型設計模式,它定義了一系列算法,并將每個算法封裝在獨立的類中,使得它們可以互相替換。策略模式讓算法的變化獨立于使用它的客戶端,從而使得客戶端可以根據需要動態切換算法,而不需要修改其代碼。策略模式的核心是將算法與使用算法的客戶端解耦,使得算法可以獨立于客戶端變化。
**Context:**持有一個策略對象的引用,負責調用策略的具體實現。
**Strategy:**定義所有支持的算法的公共接口。
**ConcreteStrategy:**實現Strategy接口,提供具體的算法實現。
使用場景
多種算法切換:如排序算法(快速排序、冒泡排序等)或支付方式(信用卡、支付寶等)。
避免條件語句:當代碼中有大量條件分支用于選擇不同行為時,可以用策略模式替代。
算法復用:當多個類需要共享相同的行為,但行為的具體實現不同時。
動態切換行為:如游戲中的角色在不同狀態下使用不同的攻擊策略。
測試與調試:策略模式可以方便地替換算法的實現,便于測試和調試。
解決的問題
代碼重復問題:
如果多個類使用相同的算法,但算法的實現分散在各處,會導致代碼重復。策略模式將算法集中管理,避免重復。
緊耦合問題:
在傳統設計中,算法直接嵌入在客戶端代碼中,導致客戶端與算法緊耦合。策略模式通過將算法抽象為接口,解耦了客戶端和具體算法。
擴展性問題:
新增算法時,需要修改客戶端代碼。策略模式允許動態添加新算法,而無需修改現有代碼。
條件分支問題:
當代碼中有大量條件分支用于選擇不同行為時,策略模式可以將其替換為對象的多態調用,使代碼更清晰。
優點
**開閉原則:**新增算法無需修改現有代碼,只需添加新的策略類。
**解耦:**將算法的實現與使用分離,提高代碼的靈活性和可維護性。
**復用性:**策略類可以在不同上下文中復用。
**簡化測試:**每個策略類可以獨立測試。
缺點
**類數量增加:**每個算法都需要一個單獨的類,可能導致類的數量增多。
**客戶端需要了解策略:**客戶端需要知道有哪些策略,并選擇合適的策略。
**性能開銷:**策略模式可能引入額外的對象創建和調用開銷。
示例代碼
如下代碼中,Context類(即客戶端)是穩定、可以不變的,變化的是策略,而策略是根據運行時的實際情況來選擇的。通過繼承Strategy類并重寫execute()接口實現策略的擴展。
#include <iostream>
#include <memory>// 抽象策略接口
class Strategy {
public:virtual void execute() const = 0;virtual ~Strategy() = default; // 虛析構函數,確保正確釋放資源
};// 具體策略A
class ConcreteStrategyA : public Strategy {
public:void execute() const override {std::cout << "執行策略A" << std::endl;}
};// 具體策略B
class ConcreteStrategyB : public Strategy {
public:void execute() const override {std::cout << "執行策略B" << std::endl;}
};// 上下文類,持有策略對象并調用其方法
class Context {
private:std::unique_ptr<Strategy> strategy; // 使用智能指針管理策略對象public:// 構造函數,允許傳入策略對象Context(std::unique_ptr<Strategy> s) : strategy(std::move(s)) {}// 設置策略void setStrategy(std::unique_ptr<Strategy> s) {strategy = std::move(s);}// 執行策略void executeStrategy() const {if (strategy) {strategy->execute();} else {std::cout << "未設置策略" << std::endl;}}
};int main() {// 創建上下文對象,并初始化為策略AContext context(std::make_unique<ConcreteStrategyA>());context.executeStrategy(); // 輸出: 執行策略A// 動態切換到策略Bcontext.setStrategy(std::make_unique<ConcreteStrategyB>());context.executeStrategy(); // 輸出: 執行策略Breturn 0;
}
代碼說明
?Strategy:抽象策略接口,定義了所有具體策略類必須實現的方法execute()。
?ConcreteStrategyA? 和 ?ConcreteStrategyB:具體策略類,分別實現了不同的算法或行為。
?Context:上下文類,持有一個策略對象的引用,并提供了設置策略和執行策略的方法。
?智能指針:使用std::unique_ptr管理策略對象的生命周期,避免內存泄漏。
運行結果
執行策略A
執行策略B
總結
通過策略模式,我們可以將算法的實現與使用算法的環境解耦,使得算法可以獨立于客戶端代碼進行擴展和修改。這種設計模式特別適用于需要動態切換算法的場景。