设计模式十:decorator(装饰)——对象结构型模式

decorator(装饰)——对象结构型模式

 

1.意图
动态地给一个对象添加一些额外的职责,就功能来说,decorator比生成子类更灵活

 

2.别名
包装器wrapper

 

3.动机
有时候我们希望给某个对象而不是整个类添加一些功能。
使用继承机制是添加功能的一种有效途径,但是不够灵活,因为用户不能控制对组件增加功能的时机和方式。
一种比较灵活的方式就是把一个组件嵌入到另一个对象中,由这个对象来增加新的功能。
我们称这个嵌入的对象为装饰,这个装饰与他所装饰的组件接口一致,因此它对使用该组件的客户透明。它将客户的请求转发给该组件,并且可能在转发前后执行一些额外的动作。透明性可以使你递归嵌套多个装饰。

 

4.适用性
1)在不影响其他对象的情况下,以动态透明的方式给单个对象添加职责。
2)处理那些可以撤销的职责
3)当不能采用生成子类的方式进行扩充时
一种情况是可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类的数目成爆炸性增长。
另一种情况是因为类定义被隐藏,或者类定义不能用于生成子类。

 

5.结构

参考:http://www.cnblogs.com/babyzone2004/archive/2010/09/15/1826906.html

 

6.参与者
component
定义一个对象接口,可以给这些对象动态地添加职责
concreteComponent
定义一个对象,可以给这个对象添加一些职责
Decorator
维持一个指向component的指针,并定义一个与component接口一致的接口
concreteDecorator
向组件添加职责

 

7.协作
decorator将请求转发给它的component对象,并且有可能在转发请求前后执行一些附加的动作

 

8.效果
有两个优点和两个缺点
1)比静态继承更灵活
2)避免在层次结构高层的类有太多的特征
可以在decorator上一点一点的增加功能
3)decorator和它的component不一样
一个被装饰的组件和这个组件还是有差别的
4)有许多小对象
这些对象仅仅在他们互相连接的方式上有所不同,而不是他们的类或者是他们的属性值有所不同

 

9.实现
要注意的地方
1)接口的一致性
所有的concreteDecorator必须有一个公共的父类
2)省略抽象的decorator类
当你仅添加一个职责时,没有必要定义抽象的decorator类
3)保持component类的简单性
为保证接口的一致性,组件和装饰必须有一个公共的component父类。因此保持这个类的简单性是很重要的
4)改变对象外壳和改变对象内核
可以将decorator看成是对象的外壳,可以改变这个对象的行为。另外一种是改变对象的内核,比如strategy

 

10.代码示例

#include<iostream>
using namespace std;

class component
{
    public:
    virtual void show(){}
};

class concreteComponent:public component
{
    public:
    void show()
    {
        cout<<"concrete component"<<endl;
    }
};

class concreteComponentB:public component
{
    public:
    void show()
    {
        cout<<"another concrete component called BBBB"<<endl;
    }
};

class decorator:public component
{
    public:
    decorator(component *co)
    {
        c = co;
    }
    void show()
    {
        c->show();
        cout<<"decorator call show"<<endl;
    }
    private:
    component *c;
};

class concreteDecoratorA:public decorator
{
    public:
    concreteDecoratorA(component *co):decorator(co){}
    void show()
    {
        decorator::show();
        cout<<"adding decorator A"<<endl;
    }
};

class concreteDecoratorB:public decorator
{
    public:
    concreteDecoratorB(component *co):decorator(co){}
    void show()
    {
        decorator::show();
        cout<<"adding decorator BBBBB"<<endl;
    }
};

int main()
{
    component *conc = new concreteComponent();
    component *d = new concreteDecoratorA(conc);
    d->show();
    
    cout<<endl;
    conc = new concreteComponentB();
    component *cd = new concreteDecoratorA(conc);
    cd->show();
    
    cout<<endl;
    component *comp = new concreteDecoratorB(conc);
    comp->show();
}

 

11.相关模式
adapter:
decorator和adapter不同,因为装饰仅改变对象的职责而不改变对象的接口,而适配器改变了对象的接口
composite:
可以将装饰器看成一个退化的,仅有一个组件的组合,然而装饰器仅给对象增加一些新的职能,他的目的不在于对象的聚集
strategy:
用一个装饰你可以改变对象的外表,而strategy模式使你可以改变对象的内核,这是改变对象的两种途径。

 

posted @ 2012-05-19 22:09  w0w0  阅读(299)  评论(0)    收藏  举报