简介
装饰者模式可以动态地给一个对象添加行为,相对通过继承来扩展功能,它是一个灵活的选择。装饰者模式也使用了继承,只是为了统一接口,如果去除 CDecorator 和 CComponent 的继承关系,就有些像桥接模式了。主要区别是装饰者不需要动态的改变被装饰的对象,而桥接模式是多个维度独立的变化。
UML 类图
示例
陈奕迅有一首歌,last order,其中有句歌词,“麻烦你 加冰威士忌 对不起 来个 DOUBLE 的”。在这里我们假定威士忌是已经实现的类,不能再改动了。那就需要装饰者登场了。这里实现了加冰威士忌,也实现了来个 double 的。
装饰类,decorator.h
#include <iostream>
using namespace std;
class CWine
{
public:
virtual string GetName() = 0;
virtual double GetCost() = 0;};
class CWhisky:public CWine
{
public:
string GetName()
{return "Whisky";}
double GetCost()
{return 60.0;}
};
class CWineDecorator:public CWine
{
public:
CWineDecorator(CWine* pWine):m_pWine(pWine){};
string GetName()
{return m_pWine->GetName();
}
double GetCost()
{return m_pWine->GetCost();
}
public:
CWine* m_pWine;
};
class CIceDecorator:public CWineDecorator
{
public:
CIceDecorator(CWine* pWine):CWineDecorator(pWine){}
string GetName()
{return m_pWine->GetName().append("+Ice");
}
double GetCost()
{return m_pWine->GetCost() + 10;
}
};
客户端调用,main.cpp
#include "decorator.h"
#define SAFE_DELETE(p) if(p){delete (p); (p) = NULL;}
int main(int argc, char* argv[])
{
CWine* pWhisky = new CWhisky;
CWine* pIceWhisky = new CIceDecorator(pWhisky);
std::cout<<"Name:"<<pIceWhisky->GetName().c_str()<<endl;
std::cout<<"Price:"<<pIceWhisky->GetCost()<<endl;
CWine* pDoubleIceWhisky = new CIceDecorator(pIceWhisky);
std::cout<<"Name:"<<pDoubleIceWhisky->GetName().c_str()<<endl;
std::cout<<"Price:"<<pDoubleIceWhisky->GetCost()<<endl;
SAFE_DELETE(pDoubleIceWhisky);
SAFE_DELETE(pWhisky);
SAFE_DELETE(pIceWhisky);
return 0;
}
输出结果如下:
Name:Whisky+Ice
Price:70
Name:Whisky+Ice+Ice
Price:80