设计模式(二):策略模式

简单工厂模式是客户告诉工厂所需要的对象,然后由工厂生产对象交给客户,客户去具体考虑的使用对象中的方法。而策略模式则有所不同,客户自己创建对象,但是当客户需要调用对象的方法时,则交由另一个环境角色类(Context)来实现,客户本身不关心方法的具体实现过程。
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。在这种模式中,主要有三种角色:

  • 抽象策略角色: 策略类,通常由一个接口或者抽象类实现。
  • 具体策略角色:包装了相关的算法和行为。
  • 环境角色:持有一个策略类的引用,最终给客户端调用。

简单来说,策略模式中客户产生其所想要的具体策略所对应的对象,并传给环境角色,由环境角色来完成具体策略的调用然后返回给客户。

还是以计算器为例,当客户需要加法运算时,就生产一个加法运算的对象,并输入加法运算的两个操作数,这时候把这个对象丢给环境角色,环境角色就会去调用具体实现加法的算法并将结果返回给客户。因此策略模式的优点是隔离了客户和具体方法,适合类中的成员以方法为主、算法经常变动的情况。但是策略模式也有明显的缺点,那就是在客户端去判断应该使用哪一个对象并要生产它,那么现在我们考虑将策略模式与简单工厂模式相结合,看看会有什么效果。我们给工厂角色加入环境角色的功能,也就是说对象的生产仍然通过客户告诉工厂角色来完成,同时工厂角色调用所产生对象的具体方法并将结果返回给客户。这么做的好处是客户无需关心对象的生产和具体方法的实现,在客户端只需知道工厂角色一个类就可以,综合了两种模式的优点。

综合回顾一下三种模式,试想有一个机器,它承担着工厂角色、环境角色或是两者结合的职责。在简单工厂模式中,客户在机器上输入对象的名称,机器就把这个对象生产出来,客户拿到这个对象就能使用它的方法;在策略模式中,客户把自己手里的对象放到这个机器里,机器去调用对象的方法,把结果显示给客户;而在两种模式相结合的情况下,客户在机器上输入对象的名称,机器把这个对象生产出来并调用它的方法,最后把结果显示给客户。

下面给出策略模式代码,由于运算基类、具体运算类和简单工厂模式一样就不再重复了,只给出环境角色类和客户端部分。

class Context//环境角色类
{
private:
	COperation* op;//指向客户产生的对象
public:
	Context(COperation* temp, int firstNum, int secondNum)
	{
		op=temp;
		op->SetFirst(firstNum);
		op->SetSecond(secondNum);
	}
	double GetResult()//调用对象的具体方法
	{
		return op->GetResult();
	}
	~Context()
	{
		delete op;
	}
};

int main()
{
	int firstNum, secondNum;
	char oper;
	cout << "Please input first number:" << endl;
	cin >> firstNum;
	cout << "Please input operator:" << endl;
	cin >> oper;
	cout << "Please input second number:" << endl;
	cin >> secondNum;
	Context *context;
	switch(oper)
	{
	case '+':
		context=new Context(new CAdd(), firstNum, secondNum);
		break;
	case '-':
		context=new Context(new CSub(), firstNum, secondNum);
		break;
	}
	cout << "The result is: " << context->GetResult() << endl;
	return 0;
}

下面是两种模式相结合的代码:

class FactoryContext//简单工厂与策略模式混合类
{
private:
	COperation* op;
public:
	FactoryContext(char cType, int firstNum, int secondNum)
	{
		switch (cType)//根据客户要求生产对象
		{
		case '+':
			op=new CAdd();
			op->SetFirst(firstNum);
			op->SetSecond(secondNum);
			break;
		case '-':
			op=new CSub();
			op->SetFirst(firstNum);
			op->SetSecond(secondNum);
			break;
		}
	}
	double GetResult()//调用所生产对象的具体方法
	{
		return op->GetResult();
	}
	~FactoryContext()
	{
		delete op;
	}
};

int main()//客户端
{
	int firstNum, secondNum;
	char oper;
	cout << "Please input first number:" << endl;
	cin >> firstNum;
	cout << "Please input operator:" << endl;
	cin >> oper;
	cout << "Please input second number:" << endl;
	cin >> secondNum;
	FactoryContext *conFactory = new FactoryContext(oper, firstNum, secondNum);
	cout << "The result is: " << conFactory->GetResult() << endl;
	delete conFactory;
	return 0;
}

 

posted @ 2014-10-19 19:05  Paradox0224  阅读(203)  评论(0编辑  收藏  举报