Strategy 策略模式
2016-07-15 14:51
399 查看
意图
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。动机
策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。就像上面的加班工资,不同的加班情况,有不同的算法。我们不能在程序中将计算工资的算法进行硬编码,而是能自由的变化的。这就是策略模式。刚刚加班回来;哎,公司规定平时加班只有10块钱的餐补;星期六和星期天加班,只给串休假;在国家规定的节假日按照3倍工资发放。那么对于这么多的计算加班费的方法,公司的OA系统是如何进行做的呢?各种计算加班费的情况就可以认为是策略模式
适用性
许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
结构
![](https://images2015.cnblogs.com/blog/461913/201607/461913-20160715152444045-1586600347.png)
参与者
Strategy:定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;ConcreteStrategy:实现Strategy接口的具体算法;
Context:使用一个ConcreteStrategy对象来配置;维护一个对Stategy对象的引用,同时,可以定义一个接口来让Stategy访问它的数据。
效果
相关算法系列Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。实现
纯策略模式,实际上就是父类为纯虚函数,子类根据需求实现各种方法#include <iostream> using namespace std; // The abstract strategy class Strategy { public: virtual void AlgorithmInterface() = 0; }; class ConcreteStrategyA : public Strategy { public: void AlgorithmInterface() { cout<<"I am from ConcreteStrategyA."<<endl; } }; class ConcreteStrategyB : public Strategy { public: void AlgorithmInterface() { cout<<"I am from ConcreteStrategyB."<<endl; } }; class ConcreteStrategyC : public Strategy { public: void AlgorithmInterface() { cout<<"I am from ConcreteStrategyC."<<endl; } }; class Context { public: Context(Strategy *pStrategyArg) : pStrategy(pStrategyArg) { } void ContextInterface() { pStrategy->AlgorithmInterface(); } private: Strategy *pStrategy; }; int main() { // Create the Strategy Strategy *pStrategyA = new ConcreteStrategyA; Strategy *pStrategyB = new ConcreteStrategyB; Strategy *pStrategyC = new ConcreteStrategyC; Context *pContextA = new Context(pStrategyA); Context *pContextB = new Context(pStrategyB); Context *pContextC = new Context(pStrategyC); pContextA->ContextInterface(); pContextB->ContextInterface(); pContextC->ContextInterface(); if (pStrategyA) delete pStrategyA; if (pStrategyB) delete pStrategyB; if (pStrategyC) delete pStrategyC; if (pContextA) delete pContextA; if (pContextB) delete pContextB; if (pContextC) delete pContextC; }
在实际操作的过程中,我们会发现,在main函数中,也就是在客户端使用策略模式时,会创建非常多的Strategy,而这样就莫名的增加了客户端的压力,让客户端的复杂度陡然增加了。那么,我们就可以借鉴简单工厂模式,使策略模式和简单工厂模式相结合,从而减轻客户端的压力,代码实现如下:
#include <iostream> using namespace std; // Define the strategy type typedef enum StrategyType { StrategyA, StrategyB, StrategyC }STRATEGYTYPE; // The abstract strategy class Strategy { public: virtual void AlgorithmInterface() = 0; virtual ~Strategy() = 0; // 谢谢hellowei提出的bug,具体可以参见评论 }; Strategy::~Strategy() {} class ConcreteStrategyA : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyA." << endl; } ~ConcreteStrategyA(){} }; class ConcreteStrategyB : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyB." << endl; } ~ConcreteStrategyB(){} }; class ConcreteStrategyC : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyC." << endl; } ~ConcreteStrategyC(){} }; class Context { public: Context(STRATEGYTYPE strategyType) { switch (strategyType) { case StrategyA: pStrategy = new ConcreteStrategyA; break; case StrategyB: pStrategy = new ConcreteStrategyB; break; case StrategyC: pStrategy = new ConcreteStrategyC; break; default: break; } } ~Context() { if (pStrategy) delete pStrategy; } void ContextInterface() { if (pStrategy) pStrategy->AlgorithmInterface(); } private: Strategy *pStrategy; }; int main() { Context *pContext = new Context(StrategyA); pContext->ContextInterface(); if (pContext) delete pContext; }
相关文章推荐
- AsyncTask的使用和源码分析
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
- Ubuntu系统下android开发环境配置
- List,Map和Set的区别
- 洛谷 P1541 乌龟棋
- 有界面(Activity或其他View)的SDK项目混淆发布
- Xcode7 真机调试(免证书)
- Exchange Server 2010 全新部署篇十一:在PEK1-MBX-02上安装邮箱服务器角色
- 日常代码
- XNA3到4的转换
- Nova 组件如何协同工作 - 每天5分钟玩转 OpenStack(24)
- 不能远程连接mysql解决方法
- 在学习HTML——form表单中的label标签时的一点小体会
- Android 应用的数据库
- ios7 页面适配问题---1
- c++ vector用法(转)
- md5密码加盐
- 搞不清FastCgi与PHP-fpm之间是个什么样的关系
- Nginx 忽略URL大小写配置
- 关于内存的分段与分页机制