策略模式简介
在解决一个某个项目的实际问题时,可能会用到不同的算法,问题不固定,解决问题的算法也不固定,就像核算不同级别员工的工资一样。策略模式就是为了适用于这一种情况。
策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户而变化。
策略模式结构
策略模式由上下文类和策略类组成,具体如下:
- Context(上下文类) :上下文类是决定使用何种算法的角色,可以根据不同的具体问题时实例化不同的具体策略类对象;
- Strategy(抽象策略类):抽象策略类,使上下文类可以无差别的调用不同的具体策略的方法;
- ConcreteStrategy(具体策略类):具体算法。
策略模式代码实例
一个简单的实现代码:
#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;
}
一个与简单工厂模式结合的例子:
#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;
};
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;
}
策略模式总结
优点:
- 符合开闭原则,策略模式易于扩展;
- 客户端可以无差别地通过公共接口调用,灵活的调用不同的算法策略;
- 提供了一个算法族管理机制和维护机制。
缺点:
- 客户端必须要知道所有的策略,以便在使用时按需实例化具体策略;
- 系统会产生很多单独的类,增加系统中类的数量;
- 客户端在同一时间只能使用一种策略。
适用环境:
- 系统需要在一个算法族中动态选择一种算法,可以将这些算法封装到多个具体算法类中;
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装与算法相关的数据结构,可以提高算法的安全性。