策略模式(Strategy Pattern)定义了一些列的算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活、可维护、可扩展。
exp:一些主流的Web站点中,都提供了多种不同的登录方式。比如账号密码登录、手机验证码登录和第三方登录。为了方便维护不同的登录方式。
这使得算法可以独立于它的客户端而变化,也就是说这些算法所完成的功能类型是一样的,对外接口也是一样的,只是不同的策略为引起环境角色表现出不同的行为。
相比于使用大量的if…else,使用策略模式可以降低复杂度,使得代码更容易维护。
缺点:可能需要定义大量的策略类,并且这些策略类都要提供给客户的。
【环境角色】持有一个策略类的引用,最终给客户端调用。
传统的策略模式实现:
#includeusing 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(HurrtType 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()" < blood(); } private: Hurt* m_pHurt; }; //环境角色类,游戏角色弓箭手,实现模板传递策略。 template class Archer { public: void attack() { m_hurt.blood(); } private: T m_hurt; } int main() { Archer* arc = new Archer; arc->attack(); delete arc; arc = nullptr; return 0; }
使用函数指针实现策略模式
#incliude#include 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 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; }



