Posted on 2008-06-09 20:15
阿呆 阅读(496)
评论(1) 编辑 收藏 引用 所属分类:
设计模式学习笔记
装饰者模式定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
设计原则:类应该对扩展开放,对修改关闭
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为。
·装饰者和被装饰者对象有相同的超类型
·你可以用一个或多个装饰者包装一个对象
·既然装饰者和被装饰者对象有相同的超类型,所以,在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
·装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
·对象可以在任何时候被装饰,所以,可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象。
在上图中,让Decorator继承自Component并不是要继承Component的行为,而是因为装饰者与被装饰者必须是一样的类型(这样装饰者才能取代被装饰者),这是相当关键的地方。在这里,我们利用继承达到“类型匹配”而不是利用继承获得行为。
而装饰者的行为是如何加入的呢?将装饰者与组建组合时,就是在加入行为。所得到的新行为,并不是来自继承,而是由组合对象得来的。
星巴兹(StarBuzz)咖啡:
最初的类设计为下边这个样子:
但是,当顾客需要加调料时怎么办呢?如果将加了某种调料的咖啡设计成另外一个类,那么将引起类爆炸。我们采用如下的做法:以饮料为主体,然后在运行时以调料来装饰(decorate)饮料。
![](http://www.cppblog.com/images/cppblog_com/adai123/Bsse.JPG)
StarBuzz.h:
1
#ifndef __STARBUZZ_H__
2
#define __STARBUZZ_H__
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include <atlstr.h>
5
#include <iostream>
6
using namespace std;
7![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
8
#ifdef UNICODE
9
#define cout wcout
10
#endif
11![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
12![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
13
//定义父类
14
class CBeverage
15![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
16
public:
17
CBeverage()
18![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
m_description = _T("Unknow Beverage");
20
m_cost = 0.0F;
21
}
22![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
23
virtual ~CBeverage()
24![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
cout << _T("~CBeverage") << endl;
26
}
27![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
28
virtual CString GetDescription()
29![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
30
return m_description;
31
}
32![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
33
virtual float GetCost()
34![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
35
return m_cost;
36
}
37
protected:
38
CString m_description;
39
float m_cost;
40
};
41![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
42
//定义咖啡类1
43
class CHouseBlend : public CBeverage
44![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
45
public:
46
CHouseBlend()
47![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
48
m_description = _T("HouseBlend");
49
m_cost = 2.4F;
50
}
51![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
52
~CHouseBlend()
53![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
54
cout << _T("~CHouseBlend") << endl;
55
}
56![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
57
virtual CString GetDescription()
58![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
59
return m_description;
60
}
61
virtual float GetCost()
62![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
63
return m_cost;
64
}
65
};
66![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
67
//定义咖啡类2
68
class CDarkRoast : public CBeverage
69![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
70
public:
71![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CDarkRoast()/**//*:m_description(_T("HouseBlend")),m_cost(6)*/
72![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
73
m_description = _T("DarkRoast");
74
m_cost = 2.4F;
75
}
76
77
~CDarkRoast()
78![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
79
cout << _T("~CDarkRoast") << endl;
80
}
81![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
82
virtual CString GetDescription()
83![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
84
return m_description;
85
}
86
virtual float GetCost()
87![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
88
return m_cost;
89
}
90
};
91![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
92
//定义咖啡类3
93
class CEspresso : public CBeverage
94![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
95
public:
96
CEspresso()
97![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
98
m_description = _T("Espresso");
99
m_cost = 2.4F;
100
}
101![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
102
~CEspresso()
103![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
104
cout << _T("~CEspresso") << endl;
105
}
106![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
107
virtual CString GetDescription()
108![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
109
return m_description;
110
}
111
virtual float GetCost()
112![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
113
return m_cost;
114
}
115
};
116![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
117
//定义咖啡类4
118
class CDecaf : public CBeverage
119![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
120
public:
121
CDecaf()
122![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
123
m_description = _T("Decaf");
124
m_cost = 2.4F;
125
}
126![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
127
~CDecaf()
128![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
129
cout << _T("~CDecaf") << endl;
130
}
131![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
132
virtual CString GetDescription()
133![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
134
return m_description;
135
}
136
virtual float GetCost()
137![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
138
return m_cost;
139
}
140
};
141![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
142![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
143
//定义调料类
144
class CCondiment : public CBeverage
145![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
146
public:
147
CCondiment()
148![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
149
m_pbeverage = NULL;
150
m_description = _T("Unknow Condiment");
151
m_cost = 0.0F;
152
}
153
~CCondiment()
154![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
167
};
168![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
169![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
170
//具体的调料1
171
class CMilk : public CCondiment
172![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
173
public:
174
CMilk(CBeverage* pbev)//注意,这里是指针
175![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
176
m_pbeverage = pbev;
177
m_description = _T("Milk");
178
m_cost = 2.4F;
179
}
180![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
181
~CMilk()
182![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
183
cout << _T("~CMilk") << endl;
184
}
185![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
186
CString GetDescription()
187![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
188
return m_pbeverage->GetDescription() + _T(",") + m_description;
189
}
190
float GetCost()
191![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
192
return m_pbeverage->GetCost() + m_cost;
193
}
194
};
195![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
196
//具体的调料2
197
class CMocha : public CCondiment
198![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
199
public:
200
CMocha(CBeverage* pbev)
201![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
202
m_pbeverage = pbev;
203
m_description = _T("Mocha");
204
m_cost = 2.5F;
205
}
206![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
207
~CMocha()
208![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
209
cout << _T("~CMocha") << endl;
210
}
211![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
212
CString GetDescription()
213![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
214
return m_pbeverage->GetDescription() + _T(",") + m_description;
215
}
216
float GetCost()
217![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
218
return m_pbeverage->GetCost() + m_cost;
219
}
220
};
221![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
222
//具体的调料3
223
class CSoy : public CCondiment
224![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
225
public:
226
CSoy(CBeverage* pbev)
227![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
228
229
m_pbeverage = pbev;
230
m_description = _T("Soy");
231
m_cost = 2.6F;
232
}
233![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
234
~CSoy()
235![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
236
cout << _T("~CSoy") << endl;
237
}
238![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
239
CString GetDescription()
240![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
241
return m_pbeverage->GetDescription() + _T(",") + m_description;
242
}
243
float GetCost()
244![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
245
return m_pbeverage->GetCost() + m_cost;
246
}
247
};
248![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
249
//具体的调料4
250
class CWhip : public CCondiment
251![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
252
public:
253
CWhip(CBeverage* pbev)
254![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
255
256
m_pbeverage = pbev;
257
m_description = _T("Whip");
258
m_cost = 2.7F;
259
}
260![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
261
~CWhip()
262![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
263
cout << _T("~CWhip") << endl;
264
}
265![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
266
CString GetDescription()
267![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
268
return m_pbeverage->GetDescription() + _T(",") + m_description;
269
}
270
float GetCost()
271![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include "stdafx.h"
5
#include "StarBuzz.h"
6![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
7![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
8
int _tmain(int argc, _TCHAR* argv[])
9![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
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![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
16
cout << (LPCTSTR)pbeverage->GetDescription() << _T(": ")<< pbeverage->GetCost() << endl;
17![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
18
delete pbeverage;
19![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
20
return 0;
21
}
22![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
23![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)