策略模式(strategy)- 设计模式(十三)

作用

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也就是说,从表面上看,这一系列的算法实现相同的功能,提供一样的接口,是可以相互替换的,但是每个算法的内部实现可能不一样。
简而言之一句话,Strategy 模式是对算法的封装。处理一个问题的时候可能有多种算法,这些算法的接口 (输入参数,输出参数等)都是一致的,那么可以考虑采用Strategy 模式对这些算法进行封装,在基类中定义一个函数接口就可以了。

举个例子

想吃鸡腿,楼下有两家便利店,都可以卖鸡腿,那么,我们就可以选择取任何一家便利店,叫儿子去买,最终的结果都是儿子买回来了鸡腿,顺便给自己买了个冰激凌。
我们可以把去一家便利店买鸡腿看作是一个算法,那个就有两个算法,输入和输出(买回鸡腿)都是一样的。
那么儿子就是其中的环境类,而你是客户端,告诉儿子想吃哪家便利店的鸡腿。

优点

  • 策略模式是定义一系列算法的方法,概念上,这些算法是可以相互代替的。
  • 策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
  • 每个算法都有自己的类,测试每个算法只是调用对应的接口就行,因此简化了测试。

缺点

  • 选择调用的算法有客户端承担,并没有降低客户端选择判断的压力。
  • 客户端承担了选择的权利,因此客户端就有了知道算法具体实现的可能性,上面的例子,选择哪家便利店,只有明确知道每家店的鸡腿的口味,才能够准确的选择便利店。
  • 无论后面的每个算法实现简单与复杂,这些算法都继承共享Strategy类定义的接口,因此,可能会产生一些根本用不到的参数,比如假设便利店有很多,但是每次买鸡腿只会挑一个去买,但是对于儿子来说,剩下 的哪些便利店的信息都需要知道。(毕竟喜欢吃的冰激凌可能在其他的便利店里面有卖)
    特点:
  • 策略模式的重心不是算法的具体实现,而是怎样对这写算法进行组合、调用,这样会使得程序更灵活,可维护性和可扩展性比较好。
  • 所有的算法都可以替换,因此这些算法是具有平等性的,所有的算法实现的实现之间是完全独立的。
  • 虽然算法有很多,但是使用的时候只能选择一个算法,因此在运行的时候,这些算法是互斥的,可以在运行的过程中动态的切换某一种策略,但是只能选择其中的一种。
  • 所有算法如果有公共的行为,那么这些公共的行为是放在Strategy类里面的。
  • 算法的实现过程中有很多,只有当客户端运行时候才知道具体调用哪一种算法,就比如,便利店是客观存在的,只有在想吃鸡腿的时候才会决定去买哪一家的。

与其他设计模式的区别

  • 状态模式: 每个对象可以在其内部动态的改变自己的状态,对象状态的改变可以不停的执行的模式
  • 工厂模式: 注重对象的创建,对象的创建和调用与客户端无关,新增一个产品必须新增一个工厂,对象只知道工厂,具体的创建对象并不知道,子类决定了类的实例化
  • 模版方法: 和策略模式最像,模版模式主要是类的继承,而策略模式着重于类的组合,两者的区别也就是类的继承和组合之间的区别
  • 策略模式: 初始时改变,已经确定需要执行的算法,只执行一次,独立于客户端运行

UML 结构图

在这里插入图片描述

例子

#include <iostream>

using namespace std;

class Strategy
{
public:
	
	virtual ~Strategy(){}
	
	virtual void BuyChicken() = 0;
};

class StoreA : public Strategy
{
public:
	virtual ~StoreA(){}
	
	virtual void BuyChicken()
	{ 
		cout << "The chicken leg was bought by StoreA... " << endl; 
	}
};

class StoreB : public Strategy
{
public:
	virtual ~StoreB(){}
	
	virtual void BuyChicken()
	{ 
		cout << "The chicken leg was bought by StoreB... " << endl; 
	}
};

class Context
{
public:
	Context(Strategy* pStrategy):m_pStrategy(pStrategy){}
	~Context()
	{
		delete m_pStrategy;
		m_pStrategy = NULL;
	}
	void ContextInterface()
	{
		if(NULL != m_pStrategy)
		{
			m_pStrategy->BuyChicken();	
		}
	}
private:
	Strategy* m_pStrategy;
};

int main(int argc, char* argv[])
{
	Strategy* p1 = new StoreB();
	Context* p2 = new Context(p1);	//客户端在这个时候已经选定了算法
	p2->ContextInterface();
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章