本文以星巴克的卖的咖啡为例,首先咖啡有多种类型,不同的咖啡有不同的收费标准,现在用一种烘焙咖啡举例,用摩卡和牛奶这两种添加材料去装饰它,有的咖啡还可能被相同的材料装饰两遍。
装饰者和超类之间的关联关系是由于在初始化的过程中需要保存实例,因此才有了关联的那道线。
咖啡的种类是作为一个被装饰者,而摩卡,牛奶之类的则是作为一个装饰者,装饰者可以叠加。
#include <stdio.h> #include <iostream> //超类 抽象出来的类 class Beverage { public: Beverage() { m_descript = "unkonw beverage"; } ~Beverage(); string getdescription() { } int cost(); private: string m_descript; }; //咖啡的类型 class DarkRoast :public Beverage { public: DarkRoast() { m_descript = "DarkRoast"; } ~DarkRoast(); int cost() { return 5; } }; //给装饰者提供接口的类,继承自基类 class CondimentDecorator:public Beverage { public: CondimentDecorator(); ~CondimentDecorator(); string getdescription(); }; //牛奶的装饰者 class Milk:public CondimentDecorator { public: Milk(Beverage b) { m_b = b; } ~Milk(); int cost() { return 1 + m_b.cost(); } string getdescription() { return m_b.getdescription() + ", Milk"; } private: Beverage m_b; //把装饰者记录到实例中 }; //磨卡的装饰者 class Mocha:public CondimentDecorator { public: Mocha(Beverage b) { m_b = b; } ~Mocha(); int cost() { return 2 + m_b.cost(); } string getdescription() { return m_b.getdescription() + ", Mocha"; } private: Beverage m_b; //把装饰者记录到实例中 }; int main() { Beverage b = new DarkRoast(); //这是一个问题,内存的分配如何做,到时候如何删除呢。 b = new Milk(b); b = new Milk(b); b = new Mocha(b); return 0; }
装饰者模式:
动态的将责任附加到对象上,想要扩展功能,装饰者提供有别于继承的另外一种选择
有一个点是对扩展开放,对修改关闭,我理解的是可以添加新的装饰类,支持可扩展,但是这种机制不会做改动,设计中经常用到的一个点是可以增加代码,但是不好修改原来的老代码。
重点在于装饰者和被装饰者必须是一样的类型,我们利用继承达到了类型匹配,而不是通过继承获得了“行为”,
装饰者与组件进行组合时,就是新的行为。所得到的新的行为,并不是继承自装饰者和基础组件,而是由组合对象来的。
装饰者模式的特点:
1、装饰者对象和被装饰者对象有相同的超类型。 Beverage
2、你可以用一个或多个装饰者包装一个对象。,用Milk 和 Mocha 去装饰DarkRoast。
3、因为装饰者和被装饰者有相同的超类型,所以可以在任何时候需要原始对象的时候,用装饰过的对象来替代,(这里涉及到了分配到内存的,到时候如何释放的问题,还没有想清楚)。
4、装饰者可以所委托被装饰者的行为前或者后,加上自己的行为,以达到特定的目的。装饰者之间没有特定的相互顺序。