Head First设计模式C++实现--第三章:装饰者(Decorator)模式

来源:互联网 发布:淘宝 折扇 编辑:程序博客网 时间:2024/05/22 03:39

装饰者(Decorator)模式

一、问题的提出

有一个咖啡店需要更新订单系统,原来的设计是这样的:
由于现在需要加入各种调料:豆浆(Soy)、摩卡(Mocha)等等,各种调料收取费用不同,所以订单必须考虑这些。
比较容易想到的一种设计方式就是所有的种类都继承自Beverage,但是很明显这样造成了“类爆炸”。
第二种设计方式:在基类中添加一些变量,代表是否加上了调料(豆浆、摩卡等):
这种设计带来的问题:
1、一旦出现新的调料,就要修改代码。
2、调料价钱改变会需要修改代码。
3、如果需要多份调料,怎么办?
4、。。。。

二、认识装饰者模式

以上两种设计方式遇到的问题有:类数量爆炸、设计死板、基类加入的功能并不适用于所有子类。
现在要用一个新的做法:以Beverage为主体,运行时以调料来“装饰(Decorate)”Beverage。例如:顾客想要摩卡和奶泡深培咖啡,那么步骤如下:
1、拿一个深焙咖啡(DarkRost)对象。
2、以摩卡(Mocha)对象装饰它。
3、以奶泡(Whip)对象装饰它。
4、调用cost方法,并依赖委托(delegate)将调料的价格加上去。

特点:
1、装饰者和被装饰者有相同的超类型。
2、用一个或多个装饰者包装一个对象。
3、装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,已达到特定的目的。
4、对象可以在任何时候被装饰,所以可以在运行时动态的、不限量的使用装饰者来装饰。

定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的解决方案
类图
饮料用此类图生成的类图:


三、代码

头文件:
#ifndef DECORATE__H#define DECORATE__H#include <string>#include <iostream>using namespace std;class Beverage{public:string description;Beverage();string getDescription();virtual double cost() = 0;};class CondimentDecorator : public Beverage{public:virtual string getDescription() = 0;};//Espresso饮料class Espresso : public Beverage{public:Espresso();double cost();};//HouseBlend饮料class HouseBlend : public Beverage{public:HouseBlend();double cost();};//Mocha装饰者class Mocha : public CondimentDecorator{public:Beverage* beverage;Mocha(Beverage* beverage);string getDescription();double cost();};#endif

cpp文件:
#include "Decorate.h"Beverage::Beverage(){description = "Unknow Beverage";}string Beverage::getDescription(){return description;}Espresso::Espresso(){description = "Espresso";}double Espresso::cost(){return 1.99;}HouseBlend::HouseBlend(){description = "House Blend Coffee";}double HouseBlend::cost(){return 0.89;}Mocha::Mocha(Beverage* beverage){this->beverage = beverage;}string Mocha::getDescription(){return beverage->getDescription() + ", Mocha";}double Mocha::cost(){return 0.20 + beverage->cost();}

、总结

1、组合和委托可以用在运行时动态添加新行为
2、除了继承,装饰者可以扩展行为
3、装饰者会导师设计中出现许多小对象(用来装饰),如果过度使用,程序会变得复杂。
4、装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。

0 0