装饰者模式:spa
可以动态地往一个类中添加新的行为。相比继承是在编译时添加行为,装饰模式是在运行时添加行为。code
星巴克咖啡是讲述装饰者模式的一个很好的例子。对象
假设如今有两种咖啡:HouseBlend、DarkRoast,同时有两种调料:Milk、Mocha。那么此时咱们能够给顾客提供如下咖啡:blog
HouseBlend、HouseBlendWithMilk、HouseBlendWithMocha、HouseBlendWithMilkandMocha、继承
DarkRoast、DarkRoastWithMilk、DarkRoastWithMocha、DarkRoastWithMilkandMocha。若是每种搭配都是一个类,那么随着咖啡和调料种类的增长,将会出现类爆炸:ip
此时装饰者模式应运而生,结构图以下:get
C++实现:string
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; }
装饰者模式的一个特征是:装饰者和被装饰对象具备相同的超类型。it
reference:io