装饰者模式:
能够动态地往一个类中添加新的行为。相比继承是在编译时添加行为,装饰模式是在运行时添加行为。
星巴克咖啡是讲述装饰者模式的一个很好的例子。
假设现在有两种咖啡:HouseBlend、DarkRoast,同时有两种调料:Milk、Mocha。那么此时我们可以给顾客提供以下咖啡:
HouseBlend、HouseBlendWithMilk、HouseBlendWithMocha、HouseBlendWithMilkandMocha、
DarkRoast、DarkRoastWithMilk、DarkRoastWithMocha、DarkRoastWithMilkandMocha。如果每种搭配都是一个类,那么随着咖啡和调料种类的增加,将会出现类爆炸:
此时装饰者模式应运而生,结构图如下:
C++实现:
class Coffee { public: virtual double getCost() = 0; virtual string getDescription() = 0; }; class HouseBlend : public Coffee { public: double getCost() { return 1.24; } string getDescription() { return "HouseBlend"; } }; class DarkRoast : public Coffee { public: double getCost() { return 2.73; } string getDescription() { return "DarkRoast"; } }; class CoffeeDecorator : public Coffee { private: Coffee *decoratedCoffee; public: CoffeeDecorator(Coffee *c): decoratedCoffee(c) {} double getCost() { return decoratedCoffee->getCost(); } string getDescription() { return decoratedCoffee->getDescription(); } }; class Milk : public CoffeeDecorator { public: Milk(Coffee *c): CoffeeDecorator(c) {} double getCost() { return CoffeeDecorator::getCost() + 0.5; } string getDescription() {return CoffeeDecorator::getDescription() + ", Milk"; } }; class Mocha : public CoffeeDecorator { public: Mocha(Coffee *c): CoffeeDecorator(c) {} double getCost() { return CoffeeDecorator::getCost() + 0.7; } string getDescription() {return CoffeeDecorator::getDescription() + ", Mocha"; } }; int main() { Coffee *pc = new HouseBlend; cout << "description: " << pc->getDescription() << " cost: " << pc->getCost() << endl; pc = new Milk(pc); cout << "description: " << pc->getDescription() << " cost: " << pc->getCost() << endl; pc = new Mocha(pc); cout << "description: " << pc->getDescription() << " cost: " << pc->getCost() << endl; delete pc; }
装饰者模式的一个特征是:装饰者和被装饰对象具有相同的超类型。
reference: