在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以飞机、火车或私家车等。
在软件开发中也常常遇到类似情况,当实现某一个功能存在多种方法,可以根据环境或者条件的不同选择不同的方法来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序等。
实现:将这些算法封装成一个一个的类,动态地替换. 一个类的行为可以在运行时更改。
用途:在有多种算法相似的情况下,使用 if…else 所带来的复杂性难以维护。而且增加、删除或更换算法要修改原代码,不易维护。
策略模式把具体的算法实现从业务逻辑中剥离出来,成为一系列独立算法类,使得它们可以相互替换。
策略模式的着重点不是如何来实现算法,而是如何组织和调用这些算法,从而让我们的程序结构更加的灵活、可扩展。
策略模式就是把各个平等的具体实现进行抽象、封装成为独立的算法类,然后通过上下文和具体的算法类来进行交互。各个策略算法都是平等的,地位是一样的,正是由于各个算法的平等性,所以它们才是可以相互替换的。虽然可以动态的切换各个策略,但同一时刻只能使用一个策略。
/*
一般通用实现:策略接口、具体的策略实现、策略上下文、外部客户端
1.策略接口(IStrategy):用来约束一系列具体的策略算法
2.具体策略实现ConcreteStrategy:具体的策略实现,即具体的算法实现
3.策略上下文(Strategy Context):负责和具体的策略实现交互。
使用此策略接口来调用具体的策略所实现的算法。
*/
//Strategy.cpp
class Strategy
{
public:
virtual int doOperation(int num1, int num2) = 0;
};
//OperationAdd.cpp
class OperationAdd : public Strategy
{
public:
virtual int doOperation(int num1, int num2) {
return num1 + num2;
}
};
//OperationSubtract.cpp
class OperationSubtract : public Strategy
{
public:
virtual int doOperation(int num1, int num2) {
return num1 - num2;
}
};
//创建 Context 类。Context.cpp
class Context
{
public :
Context(Strategy *strategy){
_strategy = strategy;
}
int executeStrategy(int num1, int num2){
return _strategy->doOperation(num1, num2);
}
private :
Strategy *_strategy;
};
//使用 Context 来查看当它改变策略 Strategy 时的行为变化。
int main(void){
Strategy *strategy = NULL;
Context *context = NULL;
context = new Context(new OperationAdd);
int add = context->executeStrategy(10, 5);
context = new Context(new OperationSubtract);
int sub = context->executeStrategy(10, 5);
return 0;
}
// 优化 简单工厂类实现Context
typedef enum StrategyType{
Add,
Subtract
}STRATEGYTYPE;
class Context
{
public :
Context(STRATEGYTYPE strategyType){
switch (strategyType){
case Add:
pStrategy = new OperationAdd;
break;
case Subtract:
pStrategy = new OperationSubtract;
break;
}
~Context(){
if (pStrategy) delete pStrategy;
}
int executeStrategy(int num1, int num2){
return pStrategy->doOperation(num1, num2);
}
private :
Strategy *pStrategy;
};
int main(void){
Context *pContext = new Context(Add);
int add = pContext->executeStrategy(10, 5);
if (pContext)
delete pContext;
}