装饰者模式
装饰者模式的引入:咖啡店的实例,当咖啡店想用多种饮料与咖啡混搭的时候,会产生排列组合数量级的类,每次多加入一种搭配的饮料,就要产生许多类。为了避免类爆炸,我们可以不为每种组合做成一个类,而是把搭配饮料作为一种基础咖啡饮料的属性,这种设计的问题有:1)当某种搭配饮料的价格产生变化的时候会改变代码;2)当加入某种新型搭配饮料的时候,也需要改变代码;3)当某种搭配型饮料我们需要两份的时候无法处理;4)子类会继承许多没有意义的东西。那么如何做才能让设计同时具备以上两种设计的优势呢?即又能保证扩展的灵活性又能不产生类爆炸。
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

#ifndef BEVERAGE_H #define BEVERAGE_H #include <string> using namespace std; class Beverage { public: Beverage(string s):description(s) { } Beverage(){} virtual string getDescription() { return description; } virtual double cost() = 0; protected: string description; }; #endif
#ifndef DARKROAST_H #define DARKROAST_H #include "Beverage.h" class DarkRoast : public Beverage { public: DarkRoast ():Beverage("DarkRoast") {} double cost() { return 30; } }; #endif
#ifndef DECAF_H #define DECAF_H #include "Beverage.h" class Decaf : public Beverage { public: Decaf() : Beverage("Decaf") {} double cost() { return 50; } }; #endif
#ifndef ESPRESSO_H #define ESPRESSO_H #include "Beverage.h" class Espresso : public Beverage { public: Espresso() : Beverage("Espresso") {} double cost() { return 40; } }; #endif
#ifndef HOUSEBLEND_H #define HOUSEBLEND_H #include "Beverage.h" class HouseBlend : public Beverage { public: HouseBlend():Beverage("HouseBlend") {} double cost() { return 20; } }; #endif
#ifndef CONDIMENTDECORATOR_H #define CONDIMENTDECORATOR_H #include "Beverage.h" class CondimentDecorator : public Beverage { public: virtual string getDescription() = 0; }; #endif
#ifndef MILK_H #define MILK_H #include "CondimentDecorator.h" #include "Beverage.h" class Milk : public CondimentDecorator { private: Beverage* beverage; public: Milk( Beverage* b ) { beverage = b; } Milk(){} virtual ~Milk() { if (NULL!=beverage) { delete beverage; beverage = NULL; } } double cost () { return beverage->cost() + 0.1; } string getDescription() { return beverage->getDescription() + "," + "Milk"; } }; #endif
#ifndef MOCHA_H #define MOCHA_H #include "CondimentDecorator.h" #include "Beverage.h" class Mocha : public CondimentDecorator { private: Beverage* beverage; public: Mocha( Beverage* b ) { beverage = b; } Mocha(){} virtual ~Mocha() { if (NULL != beverage) { delete beverage; beverage = NULL; } } double cost () { return beverage->cost() + 0.2; } string getDescription() { return beverage->getDescription() + "," + "Mocha"; } }; #endif
装饰者模式存在的问题: 1)这种设计会产生许多小类,这些小类使得使用程序API的用户很难搞懂。
2)使用装饰者模式实例化组件的时候,通常需要很多new操作,会增加代码的复杂度。可以使用抽象工厂解决该问题。
3)当组件类型必须是子类的时候,装饰者将无法进行装饰。

浙公网安备 33010602011771号