【设计模式】之策略模式粗谈【2013.12.06】
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!158427611
今天看Effect c++ 其中一点【考虑virtual函数以外的其他选择】
这一节中说道了策略模式。因而有感,小结一下;
个人的语言总结就是,策略模式,分为两块:
一块存储类似的策略:表示策略的具体执行过程,实现细节。可以是【返回值相同,参数相同的一类函数】 也可以是【虚函数的方法实现】。
另一块就是使用策略的类:类中有关于策略的函数指针成员变量,类有设置此函数指针的构造函数或者其他函数,还有就是需要有一个调用策略的对外函数。
代码如下:
class GameCharacter { //游戏角色基类 public: int healthValue() const //游戏计算健康值函数,即调用策略的对外接口 { ...//做一些事前工作 int retVal = doHealthValue(); //调用策略 这里是用的虚函数的方法实现 ...//做一些事后工作 return retVal; } private: virtual int doHealthValue() const //具体的策略实现细节 子类继承后,可以重新定义它。 { ...//缺省计算实现 } };这种方法,是将角色的策略以虚函数的方式封装到了继承类中。
子类只需要继承自基类,并实现对应的策略函数就可以了。调用策略的接口由基类维护。
所以要求在设计基类之初就定义好所有策略,而且以后增加一种策略就需要在基类添加,然后子类又增加;
而且也要修改调用策略的对外接口的内部实现。或者增加调用策略对外接口。
实为繁琐。
另一种方法是使用函数指针的方法,将所有策略重新封装,不再在调用者内部实现策略。
代码如下:
class GameCharacter; //游戏角色类 策略的使用者 int defaultHealthCalc(const GameCharacter& gc) ;//默认策略函数 class GameCharacter { public: typedef int (*HealthCalcFunc)(const GameCharacter&); //声明策略函数类型为一类 explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) //构造角色,并绑定策略 : healthFunc(hcf) {} int healthValue() const //对外方法 函数内调用策略 并返回策略执行结果 { return healthFunc(*this); //调用策略 } private: HealthCalcFunc healthFunc; //内部策略成员,只是一个指针 }; class EvilBadGuy: public GameCharacter { //子类继承基类,只需要定义新的构造函数 public: explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc) : GameCharacter(hcf) {...} ... }; int loseHealthQuickly(const GameCharacter&); //一种策略方法 int loseHealthSlowly(const GameCharacter&); //另一种策略方法 EvilBadGuy ebg1(loseHealthSlowly);//绑定loseHealthSlowly策略 EvilBadGuy ebg2(loseHealthQuickly);//绑定loseHealthQuickly策略
在使用的时候只需要 ebg1和ebg2 调用 healthValue 就能根据对象内部绑定存储的不同策略类型计算出相应的策略结果。这种方法,就是将策略从角色内部分离出来。从而提高了角色的机动性,
角色只需要绑定不同的策略就可以得到同一类型对象的不同策略结果。
就算增加策略也只需要增加一个策略函数,并在使用的时候绑定构造对象就可以了,其他地方基本不用再做修改。
比第一种方法着实方便许多。
如果你想要更好的机动性,可以使用std::tr1::function 这样的方法来绑定,不但可以绑定函数指针,还可以绑定成员函数,仿函数对象。
声明策略函数类型的时候用下面的代码格式替换就可以了。
//任何兼容于GameCharacter之物,返回任何兼容于int的东西。 typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!158427611