(C++)设计模式------装饰者模式 decorator

装饰者模式(开放关闭原则: 对扩展开放,对修改关闭)

定义:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

这里用到了继承又用到了组合,继承的作用在于:达到“类型匹配”,而不是简单的利用继承获取到“行为”。如果我们以来继承的,那么类的行为只能在编译的时候静态的决定,换句话说就是行为如果不是来自超类就是子类覆盖后的版本,反之,利用组合可以吧装饰者混合着用  而且是在“运行时”。

 

意图:动态的给一个对象添加职责;即提供了“即插即用”方法,不用重新编译已有部分。

问题:要使用的对象将执行所需的基本功能。但是,可能需要为这个对像添加某些功能,这些附加的功能可能发生在对象的基本功能之前或之后。

解决方案:可以无需创建子类而扩展一个对象的功能

优点:类的层次结构大小和复杂度有了很大程度的降低

缺点:

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值