(C++)设计模式------装饰者模式 decorator
2011-10-20 21:29
495 查看
装饰者模式(开放关闭原则: 对扩展开放,对修改关闭)
定义:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
这里用到了继承又用到了组合,继承的作用在于:达到“类型匹配”,而不是简单的利用继承获取到“行为”。如果我们以来继承的,那么类的行为只能在编译的时候静态的决定,换句话说就是行为如果不是来自超类就是子类覆盖后的版本,反之,利用组合可以吧装饰者混合着用 而且是在“运行时”。
意图:动态的给一个对象添加职责;即提供了“即插即用”方法,不用重新编译已有部分。
问题:要使用的对象将执行所需的基本功能。但是,可能需要为这个对像添加某些功能,这些附加的功能可能发生在对象的基本功能之前或之后。
解决方案:可以无需创建子类而扩展一个对象的功能
优点:类的层次结构大小和复杂度有了很大程度的降低
缺点:
1)如果装饰者本身是被装饰的,那么访问装饰模式中引进的特性将是非常困难的甚至是危险的。
2)系统对装饰者的使用顺序是敏感的。
附:显然,如果要更改被装饰者的基本功能的情况是不能用装饰者模式的。
·装饰者和被装饰者对象有相同的超类型
·你可以用一个或多个装饰者包装一个对象
·既然装饰者和被装饰者对象有相同的超类型,所以,在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
·装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
·对象可以在任何时候被装饰,所以,可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象。
在上图中,让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
定义:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
这里用到了继承又用到了组合,继承的作用在于:达到“类型匹配”,而不是简单的利用继承获取到“行为”。如果我们以来继承的,那么类的行为只能在编译的时候静态的决定,换句话说就是行为如果不是来自超类就是子类覆盖后的版本,反之,利用组合可以吧装饰者混合着用 而且是在“运行时”。
意图:动态的给一个对象添加职责;即提供了“即插即用”方法,不用重新编译已有部分。
问题:要使用的对象将执行所需的基本功能。但是,可能需要为这个对像添加某些功能,这些附加的功能可能发生在对象的基本功能之前或之后。
解决方案:可以无需创建子类而扩展一个对象的功能
优点:类的层次结构大小和复杂度有了很大程度的降低
缺点:
1)如果装饰者本身是被装饰的,那么访问装饰模式中引进的特性将是非常困难的甚至是危险的。
2)系统对装饰者的使用顺序是敏感的。
附:显然,如果要更改被装饰者的基本功能的情况是不能用装饰者模式的。
·装饰者和被装饰者对象有相同的超类型
·你可以用一个或多个装饰者包装一个对象
·既然装饰者和被装饰者对象有相同的超类型,所以,在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
·装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
·对象可以在任何时候被装饰,所以,可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象。
在上图中,让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
相关文章推荐
- c++设计模式:装饰者模式(Decorator Pattern)
- 我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)
- 设计模式之C++实现(三)---装饰者模式(Decorator)
- [C++设计模式] decorator 装饰者模式
- Head First 设计模式 (三) 装饰者模式(decorator pattern) C++实现
- 我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)
- C++设计模式之装饰者模式(Decorator)
- 我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)
- 我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)
- c++设计模式:装饰者模式(Decorator Pattern)
- 设计模式示例二 Decorator(装饰者)
- [设计模式] 9 装饰者模式 Decorator
- C++设计模式之装饰者模式
- 设计模式——装饰者模式(C++)
- 设计模式之装饰者(Decorator)模式
- (设计模式)装饰者模式Decorator&Wapper-java
- 设计模式之——装饰者模式(Decorator)
- 设计模式之(Decorator)装饰者模式
- 设计模式(9)——装饰者模式(Decorator Pattern)
- 设计模式-装饰者模式(Decorator Pattern)