设计模式:装饰器模式

  • 分类:结构型模式
  • 特点:装饰器模式可以在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
  • 模式结构:
    • UML图:略(后补)
    • 组成
      • Component(抽象构件):给出一个抽象接口,以规范准备接收附加责任的对象。
      • ConcreteComponent(具体构件):定义一个将要接收附加责任的类。
      • Decorator(抽象装饰类):持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
      • ConcreteDecorator(具体装饰类):负责给构件对象添加上附加的责任。
  • 适用场景
    • 需要扩展一个类的功能,或给一个类添加附加职责。
    • 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
    • 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
  • 实例分析:
    • 在星巴克购买咖啡时,可以选用不同种类的咖啡的同时,还可以要求在其中加入各种调味品(辅料)。(例如:奶油、摩卡、糖浆等)。倘若咖啡不带劲,我们想要添加奶油、摩卡和糖浆,这时,就可以利用装饰者模式思想来实现。
  • 1、创建构件(定义饮料基类,提供名称和价钱)
//component.h
#ifndef __COMPONENT_H_
#define __COMPONENT_H_

#include<string>
using namespace std;

//饮料基类
class IBeverage
{
public:
	virtual string Name() = 0;
	virtual double Cost() = 0;
};

#endif //COMPONENT_H

2、创建具体构件(如有两款咖啡:黑咖啡和烘焙咖啡)

//concrete_component.h
#ifndef __CONCRETE_COMPONENT_H__
#define __CONCRETE_COMPONENT_H__

#include "component.h"

//***具体的饮料(咖啡)类

//黑咖啡
class HouseBlend : public IBeverage
{
public:
	string Name() { return "HouseBlend"; }
	double Cost() { return 30.0; }
};

//烘焙咖啡
class DarkRoast: public IBeverage
{
public:
	string Name() { return "DarkRoast"; }
	double Cost() { return 28.5; }
};


#endif //CONCRETE_COMPONENT_H
  • 3、创建装饰器基类(有了coffee后,就要添加调味品,其同样继承 IBeverage,并持有咖啡的实例)
//decorator.h
#ifndef __DECORATOR_H__
#define __DECORATOR_H__

#include "component.h"

//调味品
class CondimentDecorator : public IBeverage
{

public:
	CondimentDecorator(IBeverage* beverage) :m_pBeverage(beverage) {}
	
	string Name() { return m_pBeverage->Name(); }
	double Cost() { return m_pBeverage->Cost(); }

//note:是保护成员,不能是private,否则子类无法使用
protected:
	IBeverage* m_pBeverage;
};

#endif //DECORATOR_H
  • 4、创建具体装饰(添加不同调料)
#ifndef __CONCRETE_DECORATOR_H__
#define __CONCRETE_DECORATOR_H__

#include "decorator.h"

//奶油(调味品)
class Cream : public CondimentDecorator
{
public:
	//构造函数,note:因为构造函数是不可继承的,需要调用父类构造函数对父类对象进行初始化
	Cream(IBeverage* beverage) : CondimentDecorator(beverage) {}

	string Name() { return m_pBeverage->Name() + " Cream"; }
	double Cost() { return m_pBeverage->Cost() + 3.5; }
};

//摩卡
class Mocha : public CondimentDecorator
{
public:
	Mocha(IBeverage* beverage) :CondimentDecorator(beverage) {}
	string Name() { return m_pBeverage->Name() + " Mocha"; }
	double Cost() { return m_pBeverage->Cost() + 2.0; }
};

//糖浆
class Syrup : public CondimentDecorator
{
public:
	Syrup(IBeverage* beverage) :CondimentDecorator(beverage) {}

	string Name() { return m_pBeverage->Name() + " Syrup"; }
	double Cost() { return m_pBeverage->Cost() + 3.0; }
};

#endif //CONCRETE_DECORATOR_H
  • 5、创建客户端(为coffee添加各种调味料)
//main.cpp
#include<iostream>
#include "concrete_component.h"
#include "concrete_decorator.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) {if(p) delete(p); (p) = NULL;}
#endif

int main()
{
	//黑咖啡
	IBeverage* pHouseBlend = new HouseBlend();
	cout << pHouseBlend->Name() << ":" << pHouseBlend->Cost() << endl;

	//黑咖啡+奶油
	CondimentDecorator* pCream = new Cream(pHouseBlend);
	cout << pCream->Name() << ":" << pCream->Cost() << endl;

	//黑咖啡+摩卡
	CondimentDecorator* pMocha = new Mocha(pHouseBlend);
	cout << pMocha->Name() << ":" << pMocha->Cost() << endl;

	//黑咖啡+糖浆
	CondimentDecorator*  pSyrup = new Syrup(pHouseBlend);
	cout << pSyrup->Name() << ":" << pSyrup->Cost() << endl;

	//****烘烤咖啡
	IBeverage* pDarkRoast = new DarkRoast();
	cout << pDarkRoast->Name() << ":" << pDarkRoast->Cost() << endl;

	//烘烤咖啡+奶油
	CondimentDecorator * pCrameDR = new Cream(pDarkRoast);
	cout << pCrameDR->Name() << ":" << pCrameDR->Cost() << endl;
	
	//***********important***
	//烘烤咖啡+奶油+摩卡
	CondimentDecorator* pCreamMocha = new Mocha(pCrameDR);
	cout << pCreamMocha->Name() << ":" << pCreamMocha->Cost() << endl;

	//烘烤咖啡+奶油+摩卡+糖浆
	CondimentDecorator* pCreamMochaSyrup = new Syrup(pCreamMocha);
	cout << pCreamMochaSyrup->Name() << pCreamMochaSyrup->Cost() << endl;


	//****important:注意顺序
	SAFE_DELETE(pSyrup);
	SAFE_DELETE(pMocha);
	SAFE_DELETE(pCream);
	SAFE_DELETE(pHouseBlend);


	SAFE_DELETE(pCreamMochaSyrup);
	SAFE_DELETE(pCreamMocha);
	SAFE_DELETE(pCrameDR);
	SAFE_DELETE(pDarkRoast);

	system("pause");
	return 0;	
}
  • 运行结果
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值