C++ 常用設計模式學習——策略模式
阿新 • • 發佈:2021-08-06
策略模式是指定義一系列的演算法,把它們單獨封裝起來,並且使它們可以互相替換,使得演算法可以獨立於使用它的客戶端而變化,也是說這些演算法所完成的功能型別是一樣的,對外介面也是一樣的,只是不同的策略為引起環境角色(持有一個策略類的引用,最終給客戶端呼叫)表現出不同的行為。
相比於使用大量的if...else,使用策略模式可以降低複雜度,使得程式碼更容易維護。
缺點:可能需要定義大量的策略類,並且這些策略類都要提供給客戶端。
當存在以下情況時使用策略模式:
(1)許多相關的類僅僅是行為有異。“策略”提供了一種用多個行為中的一個行為來配置一個類的方法;
(2)需要使用一個演算法的不同變體;
(3)演算法使用客戶不應該知道的資料。可使用策略模式以避免暴露覆雜的、與演算法相關的資料結構;
(4)一個類定義了多種行為,並且這些行為在這個類的操作中以多個條件語句的形式出現,將相關的條件分支移入它們各自的Strategy類中以替代這些條件語句。
Strategy:定義所有支援的演算法的公共介面。Context使用這個介面來呼叫某ConcreteStrategy定義的演算法;
ConcreteStrategy:實現Strategy介面的具體演算法;
Context:使用一個ConcreteStrategy物件來配置;維護一個對Stategy物件的引用,同時,可以定義一個介面來讓Stategy訪問它的資料。
傳統的策略模式實現
/* * 關鍵程式碼:實現同一個介面。 * 以下程式碼例項中,以遊戲角色不同的攻擊方式為不同的策略,遊戲角色即為執行不同策略的環境角色。*/ #include <iostream> using namespace std; //抽象策略類,提供一個介面 class Hurt { public: virtual void blood() = 0; }; //具體的策略實現類,具體實現介面, Adc持續普通攻擊 class AdcHurt : public Hurt { public: void blood() override { cout << "Adc hurt, Blood loss" << endl; } }; //具體的策略實現類,具體實現介面, Apc技能攻擊class ApcHurt : public Hurt { public: void blood() override { cout << "Apc Hurt, Blood loss" << endl; } }; //環境角色類, 遊戲角色戰士,傳入一個策略類指標引數。 class Soldier { public: Soldier(Hurt* hurt):m_pHurt(hurt) { } //在不同的策略下,該遊戲角色表現出不同的攻擊 void attack() { m_pHurt->blood(); } private: Hurt* m_pHurt; }; //定義策略標籤 typedef enum { Hurt_Type_Adc, Hurt_Type_Apc, Hurt_Type_Num }HurtType; //環境角色類, 遊戲角色法師,傳入一個策略標籤引數。 class Mage { public: Mage(HurtType type) { switch(type) { case Hurt_Type_Adc: m_pHurt = new AdcHurt(); break; case Hurt_Type_Apc: m_pHurt = new ApcHurt(); break; default: break; } } ~Mage() { delete m_pHurt; m_pHurt = nullptr; cout << "~Mage()" << endl; } void attack() { m_pHurt->blood(); } private: Hurt* m_pHurt; }; //環境角色類, 遊戲角色弓箭手,實現模板傳遞策略。 template<typename T> class Archer { public: void attack() { m_hurt.blood(); } private: T m_hurt; }; int main() { Archer<ApcHurt>* arc = new Archer<ApcHurt>; arc->attack(); delete arc; arc = nullptr; return 0; }
使用函式指標實現策略模式
#include <iostream> #include <functional> void adcHurt() { std::cout << "Adc Hurt" << std::endl; } void apcHurt() { std::cout << "Apc Hurt" << std::endl; } //環境角色類, 使用傳統的函式指標 class Soldier { public: typedef void (*Function)(); Soldier(Function fun): m_fun(fun) { } void attack() { m_fun(); } private: Function m_fun; }; //環境角色類, 使用std::function<> class Mage { public: typedef std::function<void()> Function; Mage(Function fun): m_fun(fun) { } void attack() { m_fun(); } private: Function m_fun; }; int main() { Soldier* soldier = new Soldier(apcHurt); soldier->attack(); delete soldier; soldier = nullptr; return 0; }
本文來自部落格園,作者:Jcpeng_std,轉載請註明原文連結:https://www.cnblogs.com/JCpeng/p/15110419.html