设计模式-装饰模式(Decorator)

在 OO 设计和开发过程,可能会经常遇到以下的情况:我们需要为一个已经定义好的类
添加新的职责(操作),通常的情况我们会给定义一个新类继承自定义好的类,这样会带来
一个问题(将在本模式的讨论中给出)。通过继承的方式解决这样的情况还带来了系统的复
杂性,因为继承的深度会变得很深。而 Decorator 提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。

问题提出

现在假设要实现一个 I/O 的库,针对一些流(Stream)进行操作,如文件流(FileStream)、网络流(NetwordStream)、内存流(MemoryStream)等,同时还要对各种流进行额外的扩展操作,如加密(Crypto)、缓存(Buffered)等

1.0 版本

下面是第一种解决此问题的方式,设计一个流的基类 Stream,文件流、网络流、内存流都继承于 Stream 类来实现各自的功能,再通过继承文件流、网络流、内存流实现相应的加密xx流、缓存xx流以及加密缓存xx流……

下面是这种实现方式的类图
Solution1

看到这样一张图,应该已经能意识到这种实现方式存在的缺陷了,如果有 n 个如文件流这样的主题功能,m 个如加密这样的扩展功能,那么最后要实现的类的个数将会达到 ( Cm1 + Cm2 + … + Cmm ) x n + n + 1 个,如此众多的类令人眼花缭乱,其中势必还充斥着大量的重复代码(加密、缓存的算法),从而使代码变得更加复杂。

下面是实现代码

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
class Stream
{
public:
virtual void Read() = 0;
virtual void Write() = 0;
virtual void Seek() = 0;
};

class FileStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class NetworkStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class MemoryStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class CryptoFileStream : public FileStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
FileStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
FileStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
FileStream::Seek();
}
};

class CryptoNetWorkStream : public NetworkStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
NetworkStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
NetworkStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
NetworkStream::Seek();
}
};

class CryptoMemoryStream : public MemoryStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
MemoryStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
MemoryStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
MemoryStream::Seek();
}
};

class BufferedFileStream : public FileStream
{
public:
virtual void Read() {
// 额外的缓存操作
FileStream::Read();
}
virtual void Write() {
// 额外的缓存操作
FileStream::Write();
}
virtual void Seek() {
// 额外的缓存操作
FileStream::Seek();
}
};

class BufferedNetWorkStream : public NetworkStream
{
public:
virtual void Read() {
// 额外的缓存操作
NetworkStream::Read();
}
virtual void Write() {
// 额外的缓存操作
NetworkStream::Write();
}
virtual void Seek() {
// 额外的缓存操作
NetworkStream::Seek();
}
};

class BufferedMemoryStream : public MemoryStream
{
public:
virtual void Read() {
// 额外的缓存操作
MemoryStream::Read();
}
virtual void Write() {
// 额外的缓存操作
MemoryStream::Write();
}
virtual void Seek() {
// 额外的缓存操作
MemoryStream::Seek();
}
};

class CryptoBufferedFileStream : public FileStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
// 额外的缓存操作
FileStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
// 额外的缓存操作
FileStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
// 额外的缓存操作
FileStream::Seek();
}
};

class CryptoBufferedNetWorkStream : public NetworkStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
// 额外的缓存操作
NetworkStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
// 额外的缓存操作
NetworkStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
// 额外的缓存操作
NetworkStream::Seek();
}
};

class CryptoBufferedMemoryStream : public MemoryStream
{
public:
virtual void Read() {
// 额外的加密/解密操作
// 额外的缓存操作
MemoryStream::Read();
}
virtual void Write() {
// 额外的加密/解密操作
// 额外的缓存操作
MemoryStream::Write();
}
virtual void Seek() {
// 额外的加密/解密操作
// 额外的缓存操作
MemoryStream::Seek();
}
};

int main()
{
FileStream* s1 = new FileStream(); // 文件流

CryptoFileStream* s2 = new CryptoFileStream(); // 加密文件流

BufferedFileStream* s3 = new BufferedFileStream(); // 缓存文件流

CryptoBufferedFileStream* s4 = new CryptoBufferedFileStream(); // 加密缓存文件流

return 0;
}

2.0 版本

下面的代码使用了装饰模式的设计思想,在处理加密和缓存功能的问题上,用组合的方式取代了原来的继承方式,现在想要在文件流的基础上实现加密、缓存等操作,只要把文件流的指针传给相应的功能类即可完成额外的工作。

这种实现方式的类层次结构图如图所示

Solution2

代码实现如下

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
class Stream
{
public:
virtual void Read() = 0;
virtual void Write() = 0;
virtual void Seek() = 0;
};

class FileStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class NetworkStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class MemoryStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class CryptoStream : public Stream
{
Stream* stream;
public:
CryptoStream(Stream* stm) : stream(stm) {

}
virtual void Read() {
// 额外的加密/解密操作
stream->Read();
}
virtual void Write() {
// 额外的加密/解密操作
stream->Write();
}
virtual void Seek() {
// 额外的加密/解密操作
stream->Seek();
}
};

class BufferedStream : public Stream
{
Stream* stream;
public:
BufferedStream(Stream* stm) : stream(stm) {

}
virtual void Read() {
// 额外的缓存操作
stream->Read();
}
virtual void Write() {
// 额外的缓存操作
stream->Write();
}
virtual void Seek() {
// 额外的缓存操作
stream->Seek();
}
};

int main()
{
FileStream* s1 = new FileStream(); // 文件流

CryptoStream* s2 = new CryptoStream(s1); // 加密文件流

BufferedStream* s3 = new BufferedStream(s1); // 缓存文件流

BufferedStream* s4 = new BufferedStream(s2); // 加密缓存文件流

return 0;
}

3.0 版本

在 GoF 设计模式中,将组合在各个类中的指针 Stream* stream 放到了一个顶层类中,类层次结构图如下:

Solution3

代码实现如下:

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
class Stream
{
public:
virtual void Read() = 0;
virtual void Write() = 0;
virtual void Seek() = 0;
};

class FileStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class NetworkStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class MemoryStream : public Stream
{
public:
virtual void Read() {
// 读取文件
}
virtual void Write() {
// 写文件
}
virtual void Seek() {
// 定位文件
}
};

class DecoratorStream : public Stream
{
protected:
Stream* stream;
DecoratorStream(Stream* stm) : stream(stm) {

}
};

class CryptoStream : public DecoratorStream
{
public:
CryptoStream(Stream* stm) : DecoratorStream(stm) {

}
virtual void Read() {
// 额外的加密/解密操作
stream->Read();
}
virtual void Write() {
// 额外的加密/解密操作
stream->Write();
}
virtual void Seek() {
// 额外的加密/解密操作
stream->Seek();
}
};

class BufferedStream : public DecoratorStream
{
public:
BufferedStream(Stream* stm) : DecoratorStream(stm) {

}
virtual void Read() {
// 额外的缓存操作
stream->Read();
}
virtual void Write() {
// 额外的缓存操作
stream->Write();
}
virtual void Seek() {
// 额外的缓存操作
stream->Seek();
}
};

int main()
{
FileStream* s1 = new FileStream(); // 文件流

CryptoStream* s2 = new CryptoStream(s1); // 加密文件流

BufferedStream* s3 = new BufferedStream(s1); // 缓存文件流

BufferedStream* s4 = new BufferedStream(s2); // 加密缓存文件流

return 0;
}

总结

最后附上一张装饰器模式(Decorator Pattern)的类图

Decorator