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

装饰者(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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值