首先什麼是“策略模式”:定義了算法家族,分別封裝起來,讓他們之間可以相互替換,讓算法的變化,不會影響到使用算法的客戶。大話設計模式P23)
我們先來看看策略模式的UML類圖是怎樣的。
1、其中Context類利用ConcreteStrategy類來配置,維護Strategy的引用
2、Strategy類是算法的公共接口
3、ConcreteStrategy類則實現了算法的行為
注意:其中Context類和Strategy類是一種“聚合關系”,是一種弱的擁有關系,其與組合關系的區別是:組合關系是一種強的擁有關系,組合關系中相互之間的生命周期是相同的。而聚合關系則不要求,我的理解是:Context可以有Strategy,但是即使不存在Context,Strategy本身也是可以存在的。其中的細微差別需要好好品味。
代碼實現:
為簡便我省略掉頭文件和命名空間的聲明。
//Context class Context { public: Context(Strategy* s) : strategy(s) {} void ContextInterface() { strategy->AlgorithmInterface(); } private: Strategy *strategy; };
//Strategy class Strategy { public: virtual void AlgorithmInterface() = 0; }; //ConcreteStrategyA class ConcreteStrategyA : public Strategy { public: void AlgorithmInterface() { //do A } }; //ConcreteStrategyB class ConcreteStrategyB : public Strategy { public: void AlgorithmInterface() { //do B } };
客戶端:
int main() { //以下代碼只作示范使用,實際上用new產生的對象是在heap中的 //所以第二次new的時候,第一次產生的對象不會自動刪除,因此會產生內存洩露 //我們可以手動delete,或者利用智能指針來解決 Strategy *s = new ConcreteStrategyA(); Context *c = new Context(s); c->ContextInterface(); s = new ConcreteStrategyB(); c = new Context(s); c->ContextInterface(); return 0; }
下面我找個例子來試驗一下:游戲中根據選擇的職業不同,攻擊方式也會不同
游戲角色類
//游戲角色類 class Player { public: Player(Character* c) : pChar(c) {} void action() { pChar->attack(); } private: Character *pChar; };
職業類
//職業類接口 class Character { public: virtual void attack() = 0; }; //劍士 class Saber : public Character { public: void attack() { cout << "斬擊" << endl; } }; //弓箭手 class Archer : public Character { public: void attack() { cout << "射擊" << endl; } }; //魔法師 class Caster : public Character { public: void attack() { cout << "火球術" << endl; } };
客戶端
int main() { Player *player; cout << "魔法師攻擊: "; player = new Player(new Caster()); player->action(); cout << "劍士攻擊: "; player = new Player(new Saber()); player->action(); return 0; }
策略模式有助於我們應對算法行為的變化,例如上述的例子中,如果我們增加新的職業,我們只需要添加新職業的類,之後在人物當中配置新職業的類,我們就可以應對這種變化。
本文出自 “加和文的世界” 博客,請務必保留此出處http://xuyjun.blog.51cto.com/7470650/1303831