装饰器模式(Decorator Pattern)
定义
装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
常用场景
1.以动态透明的方式给单个对象添加职责;
2.不采用子类的方式进行扩充。
优点
装饰类和被装饰类可以独立发展,不会互相耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点
多层装饰比较复杂
C++实现
例子:
举例:制作饮料
饮料店有很多种饮料(咖啡、果汁等),在原有饮料基础上,不同的顾客会要求添加不同的配料(冰块、糖等)。此时,在不允许继承的情况下,可以将基础咖啡内嵌到另一个类中,由另一个类完成这些操作,而不破坏原有的具体饮料类,称这个嵌入的类为装饰。
类图:
代码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
class Drink
{
public:
Drink() : m_description("") {}
virtual ~Drink() {}
virtual void AddDescription(std::string str) // 添加描述
{
m_description += str;
}
void ShowDescription() // 获取描述
{
std::cout<< m_description <<std::endl;
}
private:
std::string m_description; // 对饮料的描述
};
// 具体饮料类
// 果汁
class Juice : public Drink
{
public:
Juice() : Drink()
{
AddDescription("果汁");
}
};
// 咖啡
class Cofffee : public Drink
{
public:
Cofffee() : Drink()
{
AddDescription("咖啡");
}
};
// 装饰器类
class Decorator
{
public:
Decorator(Drink* drink) : m_drink(drink) {}
virtual ~Decorator() {}
Drink* GetDrink() {return m_drink;}
virtual void AddDecorate() = 0; // 添加装饰
private:
Drink* m_drink; // 内嵌饮料引用, 外部释放
};
// 添加冰块
class Ice : public Decorator
{
public:
Ice(Drink* drink) : Decorator(drink), m_decorate(", 添加冰块")
{
}
void AddDecorate()
{
GetDrink()->AddDescription(m_decorate);
}
private:
std::string m_decorate;
};
// 添加糖
class Sugar : public Decorator
{
public:
Sugar(Drink* drink) : Decorator(drink), m_decorate(", 添加糖") {}
void AddDecorate()
{
GetDrink()->AddDescription(m_decorate);
}
private:
std::string m_decorate;
};
int main(int argc, char** argv)
{
Drink* pJuice = new Juice();
Ice* pDecoJuice = new Ice(pJuice);
pDecoJuice->AddDecorate();
pJuice->ShowDescription();
Drink* pCoffee = new Cofffee();
Sugar* pDecoCoffee1 = new Sugar(pCoffee);
pDecoCoffee1->AddDecorate();
Ice* pDecoCoffee2 = new Ice(pCoffee);
pDecoCoffee2->AddDecorate();
pCoffee->ShowDescription();
delete pDecoCoffee2;
delete pDecoCoffee1;
delete pCoffee;
delete pDecoJuice;
delete pJuice;
return 0;
}