Posted on 2008-06-09 20:15
阿呆 阅读(506)
评论(1) 编辑 收藏 引用 所属分类:
设计模式学习笔记
装饰者模式定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
设计原则:类应该对扩展开放,对修改关闭
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为。
·装饰者和被装饰者对象有相同的超类型
·你可以用一个或多个装饰者包装一个对象
·既然装饰者和被装饰者对象有相同的超类型,所以,在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
·装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
·对象可以在任何时候被装饰,所以,可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象。
在上图中,让Decorator继承自Component并不是要继承Component的行为,而是因为装饰者与被装饰者必须是一样的类型(这样装饰者才能取代被装饰者),这是相当关键的地方。在这里,我们利用继承达到“类型匹配”而不是利用继承获得行为。
而装饰者的行为是如何加入的呢?将装饰者与组建组合时,就是在加入行为。所得到的新行为,并不是来自继承,而是由组合对象得来的。
星巴兹(StarBuzz)咖啡:
最初的类设计为下边这个样子:
但是,当顾客需要加调料时怎么办呢?如果将加了某种调料的咖啡设计成另外一个类,那么将引起类爆炸。我们采用如下的做法:以饮料为主体,然后在运行时以调料来装饰(decorate)饮料。
StarBuzz.h:
1#ifndef __STARBUZZ_H__
2#define __STARBUZZ_H__
3
4#include <atlstr.h>
5#include <iostream>
6using namespace std;
7
8#ifdef UNICODE
9#define cout wcout
10#endif
11
12
13//定义父类
14class CBeverage
15{
16public:
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 }
37protected:
38 CString m_description;
39 float m_cost;
40};
41
42//定义咖啡类1
43class CHouseBlend : public CBeverage
44{
45public:
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
68class CDarkRoast : public CBeverage
69{
70public:
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
93class CEspresso : public CBeverage
94{
95public:
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
118class CDecaf : public CBeverage
119{
120public:
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//定义调料类
144class CCondiment : public CBeverage
145{
146public:
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;
162protected:
163 CBeverage* m_pbeverage;
164 CString m_description;
165 float m_cost;
166
167};
168
169
170//具体的调料1
171class CMilk : public CCondiment
172{
173public:
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
197class CMocha : public CCondiment
198{
199public:
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
223class CSoy : public CCondiment
224{
225public:
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
250class CWhip : public CCondiment
251{
252public:
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
8int _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