Posted on 2008-06-09 20:15
阿呆 阅读(512)
评论(1) 编辑 收藏 引用 所属分类:
设计模式学习笔记
装饰者模式定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
设计原则:类应该对扩展开放,对修改关闭
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为。
·装饰者和被装饰者对象有相同的超类型
·你可以用一个或多个装饰者包装一个对象
·既然装饰者和被装饰者对象有相同的超类型,所以,在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
·装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
·对象可以在任何时候被装饰,所以,可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象。
在上图中,让Decorator继承自Component并不是要继承Component的行为,而是因为装饰者与被装饰者必须是一样的类型(这样装饰者才能取代被装饰者),这是相当关键的地方。在这里,我们利用继承达到“类型匹配”而不是利用继承获得行为。
而装饰者的行为是如何加入的呢?将装饰者与组建组合时,就是在加入行为。所得到的新行为,并不是来自继承,而是由组合对象得来的。
星巴兹(StarBuzz)咖啡:
最初的类设计为下边这个样子:
但是,当顾客需要加调料时怎么办呢?如果将加了某种调料的咖啡设计成另外一个类,那么将引起类爆炸。我们采用如下的做法:以饮料为主体,然后在运行时以调料来装饰(decorate)饮料。

StarBuzz.h:
1
#ifndef __STARBUZZ_H__
2
#define __STARBUZZ_H__
3
4
#include <atlstr.h>
5
#include <iostream>
6
using namespace std;
7
8
#ifdef UNICODE
9
#define cout wcout
10
#endif
11
12
13
//定义父类
14
class CBeverage
15

{
16
public:
17
CBeverage()
18
{
19
m_description = _T("Unknow Beverage");
20
m_cost = 0.0F;
21
}
22
23
virtual ~CBeverage()
24
{
25
cout << _T("~CBeverage") << endl;
26
}
27
28
virtual CString GetDescription()
29
{
30
return m_description;
31
}
32
33
virtual float GetCost()
34
{
35
return m_cost;
36
}
37
protected:
38
CString m_description;
39
float m_cost;
40
};
41
42
//定义咖啡类1
43
class CHouseBlend : public CBeverage
44

{
45
public:
46
CHouseBlend()
47
{
48
m_description = _T("HouseBlend");
49
m_cost = 2.4F;
50
}
51
52
~CHouseBlend()
53
{
54
cout << _T("~CHouseBlend") << endl;
55
}
56
57
virtual CString GetDescription()
58
{
59
return m_description;
60
}
61
virtual float GetCost()
62
{
63
return m_cost;
64
}
65
};
66
67
//定义咖啡类2
68
class CDarkRoast : public CBeverage
69

{
70
public:
71
CDarkRoast()/**//*:m_description(_T("HouseBlend")),m_cost(6)*/
72
{
73
m_description = _T("DarkRoast");
74
m_cost = 2.4F;
75
}
76
77
~CDarkRoast()
78
{
79
cout << _T("~CDarkRoast") << endl;
80
}
81
82
virtual CString GetDescription()
83
{
84
return m_description;
85
}
86
virtual float GetCost()
87
{
88
return m_cost;
89
}
90
};
91
92
//定义咖啡类3
93
class CEspresso : public CBeverage
94

{
95
public:
96
CEspresso()
97
{
98
m_description = _T("Espresso");
99
m_cost = 2.4F;
100
}
101
102
~CEspresso()
103
{
104
cout << _T("~CEspresso") << endl;
105
}
106
107
virtual CString GetDescription()
108
{
109
return m_description;
110
}
111
virtual float GetCost()
112
{
113
return m_cost;
114
}
115
};
116
117
//定义咖啡类4
118
class CDecaf : public CBeverage
119

{
120
public:
121
CDecaf()
122
{
123
m_description = _T("Decaf");
124
m_cost = 2.4F;
125
}
126
127
~CDecaf()
128
{
129
cout << _T("~CDecaf") << endl;
130
}
131
132
virtual CString GetDescription()
133
{
134
return m_description;
135
}
136
virtual float GetCost()
137
{
138
return m_cost;
139
}
140
};
141
142
143
//定义调料类
144
class CCondiment : public CBeverage
145

{
146
public:
147
CCondiment()
148
{
149
m_pbeverage = NULL;
150
m_description = _T("Unknow Condiment");
151
m_cost = 0.0F;
152
}
153
~CCondiment()
154
{
155
//这样做不好,因为m_pbeverage所占的内存并不是在这个类中分配的.
156
//不过,如果不这么做,那么在使用的时候会出现泄露
157
delete m_pbeverage;
158
cout << _T("~CCondiment") << endl;
159
}
160
virtual CString GetDescription() = 0;
161
virtual float GetCost() = 0;
162
protected:
163
CBeverage* m_pbeverage;
164
CString m_description;
165
float m_cost;
166
167
};
168
169
170
//具体的调料1
171
class CMilk : public CCondiment
172

{
173
public:
174
CMilk(CBeverage* pbev)//注意,这里是指针
175
{
176
m_pbeverage = pbev;
177
m_description = _T("Milk");
178
m_cost = 2.4F;
179
}
180
181
~CMilk()
182
{
183
cout << _T("~CMilk") << endl;
184
}
185
186
CString GetDescription()
187
{
188
return m_pbeverage->GetDescription() + _T(",") + m_description;
189
}
190
float GetCost()
191
{
192
return m_pbeverage->GetCost() + m_cost;
193
}
194
};
195
196
//具体的调料2
197
class CMocha : public CCondiment
198

{
199
public:
200
CMocha(CBeverage* pbev)
201
{
202
m_pbeverage = pbev;
203
m_description = _T("Mocha");
204
m_cost = 2.5F;
205
}
206
207
~CMocha()
208
{
209
cout << _T("~CMocha") << endl;
210
}
211
212
CString GetDescription()
213
{
214
return m_pbeverage->GetDescription() + _T(",") + m_description;
215
}
216
float GetCost()
217
{
218
return m_pbeverage->GetCost() + m_cost;
219
}
220
};
221
222
//具体的调料3
223
class CSoy : public CCondiment
224

{
225
public:
226
CSoy(CBeverage* pbev)
227
{
228
229
m_pbeverage = pbev;
230
m_description = _T("Soy");
231
m_cost = 2.6F;
232
}
233
234
~CSoy()
235
{
236
cout << _T("~CSoy") << endl;
237
}
238
239
CString GetDescription()
240
{
241
return m_pbeverage->GetDescription() + _T(",") + m_description;
242
}
243
float GetCost()
244
{
245
return m_pbeverage->GetCost() + m_cost;
246
}
247
};
248
249
//具体的调料4
250
class CWhip : public CCondiment
251

{
252
public:
253
CWhip(CBeverage* pbev)
254
{
255
256
m_pbeverage = pbev;
257
m_description = _T("Whip");
258
m_cost = 2.7F;
259
}
260
261
~CWhip()
262
{
263
cout << _T("~CWhip") << endl;
264
}
265
266
CString GetDescription()
267
{
268
return m_pbeverage->GetDescription() + _T(",") + m_description;
269
}
270
float GetCost()
271
{
272
return m_pbeverage->GetCost() + m_cost;
273
}
274
};
275
#endif
Test:
1
// StarBuzz-DecoratePatten.cpp : Defines the entry point for the console application.
2
//
3
4
#include "stdafx.h"
5
#include "StarBuzz.h"
6
7
8
int _tmain(int argc, _TCHAR* argv[])
9

{
10
CBeverage* pbeverage = new CHouseBlend();
11
pbeverage = new CMilk(pbeverage);
12
pbeverage = new CSoy(pbeverage);
13
pbeverage = new CWhip(pbeverage);
14
pbeverage = new CMocha(pbeverage);
15
16
cout << (LPCTSTR)pbeverage->GetDescription() << _T(": ")<< pbeverage->GetCost() << endl;
17
18
delete pbeverage;
19
20
return 0;
21
}
22
23