【设计模式】策略模式
1. 什么是策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。UML结构图如下:

Strategy:抽象策略类。用来定义所有支持算法的公共接口。
ConcreteStrategy:具体策略类。继承自Strategy,封装了具体的算法或行为。
Context:上下文。持有一个Strategy的引用,最终给客户端调用。起的承上启下作用,屏蔽了用户模块对策略、算法的直接访问。
2. 策略模式的应用
-
何时使用
如果在一个系统里有许多类,它们之间的区别仅在于它们的行为;或一个系统需要动态的在几种算法中选择一种。
-
使用方法
将这些行为或算法封装成一个一个类,任意替换。
-
优点
- 算法可以自由切换;
- 避免使用多重判断条件,方便维护;
- 增加一个策略只需要实现接口即可,方便扩展;
- 公共代码放到父类(抽象策略类)当中,避免代码重复;
-
缺点
- 策略类数量增多,每个策略都是一个类,复用的可能性很小;(可以通过享元模式来克服)
- 所有策略类都需要对外暴露,客户端需要知道所有策略类,才能自行决定使用哪一个;
-
注意
如果一个系统的策略过多(四个以上),就需要考虑使用混合模式来解决策略类膨胀的问题。
3. 策略模式样例
小王的爷爷老王刚开始使用电脑,看着电脑里的各种格式.txt、docx、jpg,瞬间眼花缭乱,身为c++程序员出身的小王,立马拍着胸脯说要给爷爷写个程序,通过程序去自动的打开各种格式文件:
#include <iostream> #include <string> enum class fileType { Type_TXT, Type_DOCX, Type_PNG, }; class fileManager { public: void openTxt() { std::cout<<"txt is opened"<<std::endl; } void openDocx() { std::cout<<"word is opened"<<std::endl; } void openPng() { std::cout<<"jpg is opened"<<std::endl; } }; int main() { fileType type = fileType::Type_TXT; fileManager manager; switch(type) { case fileType::Type_TXT: file.opentxtfile(); break; case fileType::Type_DOCX: file.opendocxfile(); break; case fileType::Type_PNG: file.openpngfile(); break; default: break; } }
爷爷选择了一个txt文件,文件就打开了,爷爷笑靥如花,小王仰起了骄傲的头。
过了两天,爷爷给小王打电话,说.avi的视频文件打不开。
于是小王不得不修改了枚举类、Switch语句。
随着种类越来越多,小王不得不买了本设计模式。改成策略模式:
- 抽象策略类
class openInterface { public: virtual void open()=0; virtual ~openInterface(){} };
- 具体策略类
//txt file class txtFile:public openInterface { public: void open() override { std::cout<<"txt is opened"<<std::endl; } }; //jpg file class jgpFile:public openInterface { public: void open() override { std::cout<<"jpg is opened"<<std::endl; } };
- 管理类
class openFileManager { public: openFileManager(openInterface* pOpen) { _pOpen = pOpen; } void openFile() { _pOpen->open(); } ~openFileManager() { if(_pOpen) delete _pOpen; } private: openInterface* _pOpen; };
- 客户端
int main() { openFileManager* txtManager = new openFileManager(new txtFile); txtManager->openfile(); openFileManager* pngManager = new openFileManager(new pngFile); pngManager->openfile(); return 0; }

浙公网安备 33010602011771号