装饰(Decorator)模式又称为包装模式,可以通过一种对客户端透明的方式来扩展对象的功能, 是继承关系的一个替换方案。
装饰模式把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要使用对象时,客户端就可以有选择地,按顺序地使用装饰功能包装对象, 动态地给一个对象添加一些额外的功能。就增加功能来说,装饰模式 比生成子类的方式更为灵活,再不改变接口的前提下, 可以增强类的性能。
使用场合如下:
(1)需要扩展一个类的功能,或给一个类增加附加功能时。
(2)需要动态地给一个对象增加功能, 这些功能也可以动态的撤销。
(3)需要增加一些基本功能的排列组合以产生更多的功能,使用继承变得不现实。
装饰者模式的角色组成如下:
(1)抽象构件角色:给出一个抽象接口,以规范准备增加附加功能的对象。
(2)具体构件角色:定义一个将要增加附加功能的类。
(3)装饰角色:拥有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
(4)具体装饰角色:负责给构件对象增加附加的功能。
示例代码如下:
#include<iostream>
#include<string>
using namespace std;
//饼的基类
class Cake
{
public:
virtual string GetName()=0;
virtual double GetPrice()=0;
protected:
string name;
}
class ShreddedCake : public Cake
{
public:
ShreddedCake()
{
name="手抓饼";
}
string GetName()
{
return name;
}
double GetPrice()
{
return 5;
}
};
//配料的基类
class Condiment : public Cake
{
protected:
Cake *cake;
};
//加鸡蛋的饼
class Egg : public Condiment
{
public:
Egg(Cake *cake)
{
this->cake=cake;
}
string GetName()
{
return cake->GetName()+"+鸡蛋";
}
double GetPrice()
{
return cake->GetPrice()+1.5;
}
};
//加里脊的饼
class Tenderloin : public Condiment
{
public:
Tenderloin(Cake *cake)
{
this->cake=cake;
}
string GetName()
{
return cake->GetName()+"+里脊";
}
double GetPrice()
{
return cake->GetPrice()+2;
}
};
int main()
{
ShreddedCake *pc=new ShreddedCake;
cout << pc->GetName() << " " << pc->GetPrice() << "元" << endl;
Tenderloin *pst=new Tenderloin(pc);
cout << pst->GetName() << " " << pc->GetPrice() << "元" << endl;
Egg *pse=new Egg(pst);
cout << pse->GetName() << " " << pc->GetPrice() << "元" << endl;
delete pc;
delete pst;
delete psc;
return 0;
}