本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.youkuaiyun.com/lovelion/article/details/17517213
主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。
我应该理解和掌握的:
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.youkuaiyun.com/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) 一个系统需要动态的在几种算法中选择一种,那么可以将这些算法封装到一个个具体的算法类中,而这些具体算法类都是一个抽象算法类的子类。客户端可以选择使用任何一种算法,并只需要维持一个数据类型是抽象算法类的对象。