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

来源:互联网 发布:图标软件下载 编辑:程序博客网 时间:2024/04/28 23:49

2014-06-15 星期日 10:42:12 

Decorator,继续GOF。

1、Intent

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality

动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。

2、Also Known As

Wrapper 包装器

3、Motivation

Sometimes we want to add responsibilities to individual objects, not to an entire class. A graphical user interface toolkit, for example, should let you add properties like borders or behaviors like scrolling to any user interface component.

One way to add responsibilities is with inheritance. Inheriting a border from another class puts a border around every subclass instance. This is inflexible, however, because the choice of border is made statically. A client can't control how and when to decorate the component with a border.

​A more flexible approach is to enclose the component in another object that adds the border. The enclosing object is called a decorator. The decorator conforms to the interface of the component it decorates so that its presence is transparent to the component's clients. 

​有时我们希望给某个对象而不是整个类添加一些功能。例如,一个图形用户界面工具箱允许你对任意一个用户界面组件添加一些特性,例如边框,或是一些行为,例如窗口滚动。

使用继承机制是添加功能的一种有效途径,从其他类继承过来的边框特性可以被多个子类的实例所使用。但这种方法不够灵活,因为边框的选择是静态的,用户不能控制对组件加边框的方式和时机。

​一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框。我们称这个嵌入的对象为 装饰 。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。

4、Applicability

Use Decorator

  to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.

  for responsibilities that can be withdrawn.

  when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to 

​     support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing.

在以下情况使用享元模式:

  在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

 处理那些可以撤消的职责。

 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类

   定义被隐藏,或类定义不能用于生成子类。

5、Structure


6、代码

代码采用此链接的  http://www.2cto.com/kf/201205/132469.html。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
#include <memory>
#include <cstring>
#include <unistd.h>
 
using namespace std;
 
class FileSys
{
public:
    virtual ~FileSys()
    {
    }
     
    virtual void Operation() = 0;
  
protected:
    FileSys()
    {
    }
};
  
//定义一个具体的对象 
class MyFileSys:public FileSys
{
public:
    MyFileSys()
    {
    }
  
    ~MyFileSys()
    {
    }
     
    void Operation()
    {
        cout<<"MyFileSys operation..."<<endl;
    }
};
  
//装饰抽象类 
class Decorator:public FileSys
{
public:
    Decorator(FileSys* fileSys)
    {
        this->_fileSys = fileSys;
    }
     
    virtual ~Decorator()
    {
        delete _fileSys;
    }
     
    void Operation()
    {
    }
     
protected:
    FileSys* _fileSys;
};
  
//压缩装饰类 
class ZipDecorator:public Decorator
{
public:
    ZipDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }
  
    ~ZipDecorator()
    {
    }
     
    void Operation()
    {
        _fileSys->Operation(); //首先运行以前的功能 
         
        this->AddedZipBehavior(); //附加功能 
    }
     
    void AddedZipBehavior()
    {
        cout<<"Added Zip Behavior...."<<endl;
    }
};
  
//杀毒装饰类 
class KillVirDecorator:public Decorator
{
public:
    KillVirDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }
      
    ~KillVirDecorator()
    {
    }
     
    void Operation()
    {
        _fileSys->Operation();
        this->AddedKillVirBehavior();
    }
     
    void AddedKillVirBehavior()
    {
        cout<<"Added Kill Virus Behavior...."<<endl;
    }
};
  
//加密装饰类 
class EncryptDecorator:public Decorator
{
public:
    EncryptDecorator(FileSys* fileSys):Decorator(fileSys)
    {
    }
     
    ~EncryptDecorator()
    {
    }
     
    void Operation()
    {
        _fileSys->Operation();
        this->AddedEncrypeBehavior();
    }
     
    void AddedEncrypeBehavior()
    {
        cout<<"Added Encrypt Behavior...."<<endl;
    }
};
  
////////////////////////////////////////////////////////////////////////// 
//测试 
int main(int argc, char* argv[])
{
    FileSys* fileSys = new MyFileSys();
     
    Decorator* dec1 = new ZipDecorator(fileSys);  //在原文件系统上,加入压缩功能 
    Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基础上,加入杀毒功能 
    Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能 
 
    dec3->Operation();
    return 0;
}

如果不用decorator,要增加zip并不修改父类,该怎么做呢。以下为本人添加代码。仅给出和上面有差异的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//定义一个具体的对象 
class MyFileSys:public FileSys
{
public:
    MyFileSys()
    {
    }
  
    ~MyFileSys()
    {
    }
     
    void Operation()
    {
        cout<<"MyFileSys operation..."<<endl;
    }
     
    void AddedZipBehavior()
    {
        cout<<"Added Zip Behavior In...."<<endl;
    }
};
 
//测试 
int main(int argc, char* argv[])
{
    FileSys* fileSys = new MyFileSys();
     
    Decorator* dec1 = new ZipDecorator(fileSys);  //在原文件系统上,加入压缩功能 
    Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基础上,加入杀毒功能 
    Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能 
 
    dec3->Operation();
    (dynamic_cast<MyFileSys*>(fileSys))->AddedZipBehavior();
    return 0;
}

通过比较,可以更清楚的看出Decorator​的作用了。

7、与其他模式的区别

0 0