解释说明:动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案
抽象构件(Component):定义一个抽象接口以规范准备收附加责任的对象
具体构件(ConcreteComponent):实现抽象构件,通过装饰角色为其添加一些职责
抽象装饰类(Decorator):继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
具体装饰类(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任
优点:
Decorator 模式与继承关系的目的都是要扩展对象的功能,但是 Decorator 可以提供比继承更多的灵活性。
通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
缺点:
这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
装饰模式是针对抽象构建(Component)类型编程。但是,如果要针对具体构件(ConcreteComponent)编程,应该重新思考应用架构,以及装饰者是否合适。当然也可改变 Component 接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
适用场景
需要扩展一个类的功能,或给一个类添加附加职责。
需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类
#pragma once
#include <string>
using namespace std;
// 所有饮料的基类
class IBeverage
{
public:virtual string Name() = 0; // 名称virtual double Cost() = 0; // 价钱
};
/********** 具体的饮料(咖啡)**********/
// 黑咖啡,属于混合咖啡
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;}
};#pragma once
#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();}
protected:IBeverage* m_pBeverage;
};
/********** 具体的饮料(调味品)**********/
// 奶油
class Cream : public CondimentDecorator
{
public: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;}
};#include "component.h"
#include "decorator.h"
#include <iostream>
#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* pCreamDR = new Cream(pDarkRoast);cout << pCreamDR->Name() << " : " << pCreamDR->Cost() << endl;// 深度烘培咖啡豆 + 奶油 + 摩卡CondimentDecorator* pCreamMocha = new Mocha(pCreamDR);cout << pCreamMocha->Name() << " : " << pCreamMocha->Cost() << endl;// 深度烘培咖啡豆 + 奶油 + 摩卡 + 糖浆CondimentDecorator* pCreamMochaSyrup = new Syrup(pCreamMocha);cout << pCreamMochaSyrup->Name() << " : " << pCreamMochaSyrup->Cost() << endl;SAFE_DELETE(pSyrup);SAFE_DELETE(pMocha);SAFE_DELETE(pCream);SAFE_DELETE(pHouseBlend);SAFE_DELETE(pCreamMochaSyrup);SAFE_DELETE(pCreamMocha);SAFE_DELETE(pCreamDR);SAFE_DELETE(pDarkRoast);getchar();return 0;
}