问题
Strategy模式和Template模式要解决的问题是类似的,都是为了给业务逻辑(算法)具体实现和抽象接口之间的解耦。Strategy模式将逻辑(算法)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给组合对象实现。State模式也有类似的功能。
Strategy策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
解析:简而言之一句话,Strategy模式是对算法的封装。处理一个问题的时候可能有多种算法,这些算法的接口(输入参数,输出参数等)都一致的,那么可以考虑采用Strategy模式对这些算法进行封装,在基类中定义一个函数接口就可以了。
小demo
strategy.h
#ifndef STRATEGY_H
#define STRATEGY_H
class Strategy;
//这个类是Strategy模式的关键,也是Strategy模式和Template模式的根本区别所在。Strategy通过"组合"(委托)方式实现算法的异构,而Template模式则采取的是继承的方式。这两个模式的区别也是继承和组合两种实现接口重用的方式的区别
class Context
{
public:
Context(Strategy *pStrategy) : m_pStrategy(pStrategy){}
~Context();
void ContextInterface();
private:
Strategy* m_pStrategy;
};
class Strategy
{
public:
virtual ~Strategy(){}
virtual void AlgorithmInterface() = 0;
};
class ConcreateStrategyA : public Strategy
{
public:
virtual ~ConcreateStrategyA(){}
virtual void AlgorithmInterface();
};
class ConcreateStrategyB : public Strategy
{
public:
virtual ~ConcreateStrategyB(){}
virtual void AlgorithmInterface();
};
#endif
strategy.cpp
#include <iostream>
#include "Strategy.h"
Context::~Context()
{
delete m_pStrategy;
m_pStrategy = NULL;
}
void Context::ContextInterface()
{
if (NULL != m_pStrategy)
{
m_pStrategy->AlgorithmInterface();
}
}
void ConcreateStrategyA::AlgorithmInterface()
{
std::cout << "AlgorithmInterface Implemented by ConcreateStrategyA\n";
}
void ConcreateStrategyB::AlgorithmInterface()
{
std::cout << "AlgorithmInterface Implemented by ConcreateStrategyB\n";
}
main.cpp
#include "Strategy.h"
#include <windows.h>
int main()
{
Strategy* pStrategy = new ConcreateStrategyA();
Context* pContext = new Context(pStrategy);
pContext->ContextInterface();
delete pContext;
system("pause");
return 0;
}
//Stategy模式的代码很直观,关键是将算法的逻辑封装到一个类中
Strategy模式和Template模式实际上是实现一个抽象接口的两种方式:继承和组合之间的区别。要实现一个抽象接口,继承是一种方式:我们将抽象接口声明在基类中,将具体的实现放在具体子类中。
组合(委托)是另外一种方式:我们将接口的实现放在被组合对象中,将抽象接口放在组合类中。
另外Strategy模式很State模式也有相似之处,但是State模式注重的对象在不同的状态下不同的操作。两者之间的区别就是State模式中具体实现类中有一个指向Context的引用,而Strategy模式则没有。