posts - 7, comments - 5, trackbacks - 0, articles - 4

HeadFirst学习笔记3-装饰者模式

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

Feedback

# re: HeadFirst学习笔记3-装饰者模式  回复  更多评论   

2008-10-11 23:14 by 路人
写得很好 很受益~~

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理