本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.csdn.net/lovelion/article/details/17517213
主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。
我应该理解和掌握的:
1)能够画出这个设计模式的架构框图;
2)能够根据架构框图写出对应的伪代码;
3)这个模式的应用场景,主要优缺点。
1.装饰模式
装饰模式在不改变对象本身功能的基础上添加额外的功能,比如给照片添加一个相框。同时他也是一种替代继承的技术,使用关联取代继承;在装饰模式中引入装饰类,在装饰类中既可以调用待装饰的原有类方法,还可以新增方法,以扩充原有功能。
(1)定义
装饰模式:动态的给一个对象添加一些额外的职责。就新增功能来说,Decorator模式相比生成子类更为灵活。
1) 装饰模式结构图
2)参与者
a) Component(抽象构件):定义一个对象业务方法,是具体构建和抽象装饰类的共同父类,客户端针对它编程。
b) ConcreteComponent(具体构件):定义具体构件,实现父类业务方法,装饰类将会给这个对象增加额外的职责。
c) Decorator(抽象装饰类):抽象构件子类,用于关联一个抽象构件的指针,并定义一个与Component一致的接口,直接调用装饰之前对象的业务方法。
d) ConcreteDecorator(具体装饰类):向具体构件增加额外的职责,不同的具体装饰类增加不同的职责。调用抽象装饰类的operation方法,同时增加新的业务方法,这边是装饰额外的功能。
3) 看图写代码
/*
** FileName : DecoratorPattern
** Author : lin005
** Date : 2015/01/27
** Description : More information, please go to http://blog.csdn.net/amd123456789
*/
class Component
{
public:
virtual void operation() = 0;
};
//具体构建类
class ConcreteComponent:public Component
{
public:
void operation()
{
cout<<"ConcreteComponent"<<endl;
}
};
//抽象装饰类
class Decorator:public Component
{
public:
//注入抽象类,保持一个对component的引用
Decorator(Component* c)
{
_component = c;
}
virtual void operation()//直接调用component的方法
{
_component->operation();
}
~Decorator()
{
if(_component != NULL)
{
delete _component;
_component = NULL;
}
}
protected:
//关联一个component
Component* _component;
};
//具体状态装饰类
class ComcreteDecoratorA:public Decorator
{
public:
//注入一个component对象
ComcreteDecoratorA(Component* c):Decorator(c){}
//对客户透明,始终还是调用operation()
virtual void operation()
{
//增加state状态
addstate();
Decorator::operation();
}
//装饰类要添加的职能
void addstate()
{
cout<<"要装饰的状态方法"<<endl;
}
};
//具体行为装饰类
class ComcreteDecoratorB:public Decorator
{
public:
//注入一个component对象
ComcreteDecoratorB(Component* c):Decorator(c){}
virtual void operation()
{
//装饰行为职能
addbehavior();
Decorator::operation();
}
void addbehavior()
{
cout<<"要装饰的行为方法"<<endl;
}
};
//客户端测试
int main(int argc, const char * argv[]) {
//客户端针对抽象编程
Component *c;
Component* dA;
Component* dB;
Component* dAB;
c = new ConcreteComponent();//具体构件对象,即要装饰前的对象
dA = new ComcreteDecoratorA(c);//具体装饰对象A
dB = new ComcreteDecoratorB(c);//具体装饰对象B
dAB = new ComcreteDecoratorA(dB);//同时装饰A和B,非常方便,直接嵌套
c->operation();
dA->operation();
dB->operation();
dAB->operation();
return 0;
}
(2)总结
1)优点:
a) 对于扩展一个对象的功能,装饰模式比静态继承更灵活,也很容易重复添加一个特性,不会导致类的个数急剧增加。
b) 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,得到功能更为强大的对象。
c) 符合开闭,具体构件类和具体装饰类可以独立变化,按需增加新的具体构件类和具体装饰类。
2)缺点
a) 会产生许多小对象;这些对象仅仅在他们相互连接的方式上有所不同,而不是他们的类或是他们的属性值有所不同。
b) 对于了解这些系统的人来说,很容易对他们进行定制,但是很难学习这些系统,排错也困难。
3) 注意事项
a) 接口一致性。装饰对象的接口必须与他所装饰的component的接口是一致的。
b) 保持Component类的简单性。它应集中于定义接口而不是存储数据,对于数据的表示应延迟到子类,否则Component会变得过于复杂的庞大,难以大量使用。我们应该通过装饰类对其进行扩展。
c) 可以省略抽象的Decorator类,当你仅需要添加一个职责时,没必要定义抽象Decotator类。你常常需要处理现存的类层次结构而不是设计一个新的系统,这时可以把Decorator向Component转发请求的职责合并到ComcreteDecorator中。
d) 如果只有一个具体构件类,那么抽象装饰类可以作为该具体构件结构类的直接子类。如下图:
(3)适用场景
1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2)处理那些可以撤销的职责,按需再进行添加。同时装饰者模式的行为具有可叠加性。
3)当不能采用生成子类的方法进行扩充。一种是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种是可能因为类定义被隐藏,或类定义不能生成子类。