[设计模式][三] head first 设计模式之装饰者模式(decorator)
1 别名
包装器wrapper
2 介绍
通过使用修饰模式,可以在运行时扩充一个类的功能。原理是:增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。修饰类必须和原来的类有相同的接口。
修饰模式是类继承的另外一种选择。类继承在编译时候增加行为,而装饰模式是在运行时增加行为。
当有几个相互独立的功能需要扩充时,这个区别就变得很重要。在有些面向对象的编程语言中,类不能在运行时被创建,通常在设计的时候也不能预测到有哪几种功能组合。这就意味着要为每一种组合创建一个新类。相反,修饰模式是面向运行时候的对象实例的,这样就可以在运行时根据需要进行组合。一个修饰模式的示例是JAVA里的Java I/O Streams的实现。
3 设计原则
类应该对扩展开放,对修改关闭。
4 条件
a) 装饰者和被装饰对象有相同的超类型;
b) 你可以用一个或则多个装饰者包装一个对象;
5 定义
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
#ifndef BEVERAGE_H#define BEVERAGE_H#include <iostream>#include <string>#include <cassert>using namespace std;//装饰者模式namespace Decorator{//const definitions//////////////////////////////////////////////////////////////////////////const double ESPRESSO_PRICE = 1.99;const double HOUSEBLEND_PRICE = 0.89;const double MOCHA_PRICE = 0.20;//////////////////////////////////////////////////////////////////////////class Beverage{public: Beverage() { mDescription = "Unknown Beverage"; } virtual ~Beverage(){} virtual double cost() = 0 ; virtual string getDescription() { return mDescription; }protected: string mDescription;};//////////////////////////////////////////////////////////////////////////class Espresso : public Beverage{public: Espresso() { mDescription = "Espresso"; } virtual double cost() { return ESPRESSO_PRICE; }};//////////////////////////////////////////////////////////////////////////class HouseBlend : public Beverage{public: HouseBlend() { mDescription = "House Blend Coffee" ; } virtual double cost() { return HOUSEBLEND_PRICE; }};//////////////////////////////////////////////////////////////////////////class CondimentDecorator : public Beverage{public: virtual string getDescription() = 0;};class Mocha : public CondimentDecorator{public: Mocha(Beverage* beverage) : mBeverage(NULL) { if (beverage != NULL) { if (mBeverage != NULL) { delete mBeverage; mBeverage = NULL; } this->mBeverage = beverage; } } virtual ~Mocha() { if (mBeverage != NULL) { delete mBeverage; } } virtual string getDescription() { assert( mBeverage != NULL); return mBeverage->getDescription() + " , Mocha"; } virtual double cost() { assert( mBeverage != NULL); return MOCHA_PRICE + mBeverage->cost(); }private: Beverage* mBeverage;};//////////////////////////////////////////////////////////////////////////class StarbuzzCoffee{public: void run() { Beverage* beverage = new Espresso(); cout << beverage->getDescription().c_str() << " $" << beverage->cost() << endl; beverage = new Mocha(beverage); cout << beverage->getDescription().c_str() << " $" << beverage->cost() << endl; Beverage* beverage2 = new HouseBlend(); cout << beverage2->getDescription().c_str() << " $" << beverage2->cost() << endl; beverage2 = new Mocha(beverage2); cout << beverage2->getDescription().c_str() << " $" << beverage2->cost() << endl; beverage2 = new Mocha(beverage); cout << beverage2->getDescription().c_str() << " $" << beverage2->cost() << endl; delete beverage; delete beverage2; }};}//namespace Decorator#endif#endif