裝飾者模式: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