您的位置:首页 > 其它

【设计模式学习笔记二十二】【行为模式】【策略模式(Strategy)】

2015-02-10 08:42 716 查看
本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:/article/1610242.html

主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。

我应该理解和掌握的:

1)能够画出这个设计模式的架构框图;

2)能够根据架构框图写出对应的伪代码;

3)这个模式的应用场景,主要优缺点。

1.策略模式

条条大路通罗马,殊途同归,从某种程度上反应出策略模式,实现某一个功能有多条途径,每一条途径对应一种算法,此时我们可以使用这种设计模式来实现灵活的选择解决途径,也能够方便的增加新的解决途径。策略模式的主要目的是将算法的定义和使用分开,也就是将算法的行为和环境分开,将算法定义到专门的策略类中,每一个策略类封装了一种实现算法,使用算法的环境类针对抽象策略类进行编程,符合依赖倒转原则。出现新的算法时,只需要增加一个新的实现了抽象策略类的具体策略类即可。

(1)定义

策略模式:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。本模式使得算法可独立于使用他的客户而变化。

1) 策略模式结构图



2) 参与者

a)Strategy(策略):定义所有支持的算法的公共接口。context使用这个接口来调用某ConcreteStrategy定义的算法。
b)ConcreteStrategy(具体策略):以Strategy接口实现某具体算法,运行时具体策略对象覆盖环境类的抽象策略对象。
c)Context(上下文):用一个ConcreteStrategy对象来配置;维护一个对Strategy对象的引用;可定义一个接口来让Strategy来访问他的数据。

3) 看图写代码

/*
** FileName     : StrategyPattern
** Author       : lin005
** Date         : 2015/02/10
** Description  : More information, please go to http://blog.csdn.net/amd123456789 */
#include<iostream>
using namespace std;
//枚举变量,表示不同的策略算法
enum STRATEGY
{
	SA,//A算法
	SB //B算法
};
//抽象策略类
class Strategy
{
public:
	//声明策略类接口
	virtual void algorithm() = 0;
};
//具体策略类A
class ConcreteStrategyA : public Strategy
{
public:
	ConcreteStrategyA(){}
	//定义自己的算法实现
	void algorithm()
	{
		cout<<"this is A algorithm!"<<endl;
	}
};
//具体策略类B
class ConcreteStrategyB : public Strategy
{
public:
	ConcreteStrategyB(){}
	//定义自己的算法实现
	void algorithm()
	{
		cout<<"this is B algotithm!"<<endl;
	}
};
//上下文
class Context
{
public:
	//通过传入枚举类型,创建不同的具体策略
	Context(STRATEGY type)
	{
		if(SA == type)
		{
			p_strategy = new ConcreteStrategyA();
		}
		else if(SB == type)
		{
			p_strategy = new ConcreteStrategyB();
		}
		else
		{
			cout<<"need add new strategy in concructor!"<<endl;
		}
	}
	~Context()
	{
		if(p_strategy)
		{
			delete p_strategy;
			p_strategy = NULL;
		}
	}
	//调用创建的策略类方法
	void algorithm()
	{
		if(p_strategy)
		{
			p_strategy->algorithm();
		}
		else
		{
			cout<<"no strategy in context->algorithm()!"<<endl;
		}
	}
private:
	//持有一个策略类对象
	Strategy* p_strategy;
};
//客户端测试程序
#define SAFE_DELETE(p) if(p){delete p; p = NULL;}
int main()
{
	//创建一个上下文,通过传入类型选择不同的策略算法
	Context* c = new Context(SB);
	c->algorithm();
	return 0;
}


(2)总结

1) 优点

a) 支持开闭原则,不修改原有代码也可以灵活的增加新的算法或行为。
b)
提供了管理相关的算法族办法。使用继承把公共代码移到抽象策略类中,从而避免重复代码。
c)
消除了一些条件语句,避免堆砌在一个上下文对象中。
d)
提供了一种算法的复用机制。由于将算法单独提出出来封装在策略类中,不同的环境类可以方便的复用这些策略类。

2) 缺点

a)
客户端必须了解不同的策略类,并自行决定使用哪一个策略类。
b)
增加了对象数目,可能造成系统产生很多具体策略类。
c)
无法在客户端同时使用多个策略类。

(3)适用场景

1)
许多相关的类仅仅是行为有异。策略提供了一种用多个行为中的一个行为来配置一个类的方法。
2)
需要使用一个算法的不同变体。
3)
一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现;将相关的条件分支移入他们各自的Strategy类中以代替这些条件语句。
4)
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
5)
一个系统需要动态的在几种算法中选择一种,那么可以将这些算法封装到一个个具体的算法类中,而这些具体算法类都是一个抽象算法类的子类。客户端可以选择使用任何一种算法,并只需要维持一个数据类型是抽象算法类的对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: