設計模式之十四:Decorator(裝飾)—對象結構型模式

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、與其他模式的區別

發佈了66 篇原創文章 · 獲贊 8 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章