1 概念
策略模式:它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
2 UML图
3 C++示例代码
strategy.h
#include <iostream>
class Strategy {
public:
virtual void AlgorithmInterface() = 0;
};class StrategyA: public Strategy {
public:
void AlgorithmInterface() override;
};class StrategyB: public Strategy {
public:
void AlgorithmInterface() override;
};class StrategyC: public Strategy {
public:
void AlgorithmInterface() override;
};class Context {
public:
Context(Strategy* strategy);
void ContextInterface();
private:
Strategy* m_strategyPtr = nullptr; // 这里体现了Context与Strategy之间的聚合关系
};
strategy.cpp
#include <iostream>
#include <string>
#include "strategy.h"using namespace std;
void StrategyA::AlgorithmInterface()
{
cout << "StrategyA Algorithm" << endl;
}void StrategyB::AlgorithmInterface()
{
cout << "StrategyB Algorithm" << endl;
}void StrategyC::AlgorithmInterface()
{
cout << "StrategyC Algorithm" << endl;
}Context::Context(Strategy* strategy)
{
m_strategyPtr = strategy;
}void Context::ContextInterface()
{
if (m_strategyPtr == nullptr) {
cout << "Type is invalid" << endl;
return;
}m_strategyPtr->AlgorithmInterface();
}int main(int argc, char *argv[])
{
Strategy *strategy = nullptr;if (argc < 2) {
cout << "Input param error" << endl;
return -1;
}// 可以看到,此时客户端不仅需要认识Strategy类, 还得知道StrategyA等Strategy子类的存在
// 并且,客户端里面根据不同的条件分支new出不同的对象
int type = stoi(argv[1]);
switch (type) {
case 0:
strategy = new StrategyA;
break;
case 1:
strategy = new StrategyB;
break;
case 2:
strategy = new StrategyC;
break;
default:
break;
}if (strategy == nullptr) {
cout << "Type is invalid" << endl;
return -1;
}Context context(strategy);
context.ContextInterface();
return 0;
}
4 总结
可以看到,简单策略模式里面,客户端的代码是需要知道StrategyA、StrategyB、StrategyC的存在的,并且,在实际使用过程中,需要在客户端里面用if else或者switch case等分支语句来控制new出StrategyA、StrategyB、StrategyC,然后传入Context,再调Context的ContextInterface接口。
这种在客户端里面根据不同的条件分支new出不同的对象,正是前面讲到的工厂模式解决的问题,因此,很自然的就想到把工厂模式和策略模式结合,进一步优化代码。
策略模式与工厂模式结合的UML图
C++示例代码
strategy.h
#include <iostream>
class Strategy {
public:
virtual void AlgorithmInterface() = 0;
};class StrategyA: public Strategy {
public:
void AlgorithmInterface() override;
};class StrategyB: public Strategy {
public:
void AlgorithmInterface() override;
};class StrategyC: public Strategy {
public:
void AlgorithmInterface() override;
};class Context {
public:
Context(int type);
void ContextInterface();
private:
Strategy* m_strategyPtr = nullptr; // 这里体现了Context与Strategy之间的聚合关系
};
strategy.cpp
#include <iostream>
#include <string>
#include "strategy.h"
using namespace std;void StrategyA::AlgorithmInterface()
{
cout << "StrategyA Algorithm" << endl;
}void StrategyB::AlgorithmInterface()
{
cout << "StrategyB Algorithm" << endl;
}void StrategyC::AlgorithmInterface()
{
cout << "StrategyC Algorithm" << endl;
}Context::Context(int type)
{
switch (type) {
case 0:
m_strategyPtr = new StrategyA;
break;
case 1:
m_strategyPtr = new StrategyB;
break;
case 2:
m_strategyPtr = new StrategyC;
break;
default:
break;
}
}void Context::ContextInterface()
{
if (m_strategyPtr == nullptr) {
cout << "Type is invalid" << endl;
return;
}m_strategyPtr->AlgorithmInterface();
}int main(int argc, char *argv[])
{
if (argc < 2) {
cout << "Input param error" << endl;
return -1;
}// 可以看到,此时客户端只需要认识Context一个类就够了
int type = stoi(argv[1]);
Context context(type);
context.ContextInterface();
return 0;
}
策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。