您的位置:首页 > 编程语言 > C语言/C++

(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


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息