标题定义:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
结构
装饰模式有以下4个角色。
■ 抽象构件(Component)角色:该角色用于规范需要装饰的对象(原始对象)。
■ 具体构件(Concrete Component)角色:该角色实现抽象构件接口,定义一个需要装饰的原始类。
■ 装饰(Decorator)角色:该角色持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
■ 具体装饰(Concrete Decorator)角色:该角色负责对构件对象进行装饰。
应用
装饰模式类似于一个嵌套调用,就像俄罗斯套娃,装饰者的执行函数,会调用被装饰者的执行函数,多层装饰就存在多重调用。
在一般情况下,装饰模式可以避免在众多不同类别的属性下因为继承带来的类爆炸问题。在Head First设计模式一书中,为不同饮料和配料创建不同子类就出现了类爆炸:
使用装饰模式,可以避免反复耦合创建子类,只需要使用不同的分类装饰就可以了。重构后的类图如下:
示例
几本书上都是java版本的代码,所以想自己写一个C++的示例,没想到因为访问父类变量的问题卡了好久。只要新增一个set接口来设置一个公有变量。
#include <iostream>
using namespace std;
class Phone
{
public :
virtual void show() = 0;
};
class iPhone:public Phone{
public :
virtual void show()
{
cout<<"iPhone"<<endl;
}
};
class DecoratorPone:public Phone
{
public :
void setBasePhone(Phone* phone)
{
mPhone = phone;
}
virtual void show()
{
mPhone->show();
}
Phone* mPhone;
};
class PhoneSuit:public DecoratorPone
{
public:
PhoneSuit(Phone* phone)
{
setBasePhone(phone);
}
virtual void show()
{
cout<<"带上套套的";
mPhone->show();
}
};
class PhoneScreen:public DecoratorPone
{
public:
PhoneScreen(Phone* phone)
{
setBasePhone(phone);
}
virtual void show()
{
cout<<"贴上钢化膜的";
mPhone->show();
}
};
int main() {
Phone* myPhone = new iPhone();
cout<<"这是一个";myPhone->show();
myPhone = new PhoneSuit(myPhone);
cout<<"这是一个";myPhone->show();
myPhone = new PhoneScreen(myPhone);
cout<<"这是一个";myPhone->show();
return 0;
}
输出:
这是一个iPhone
这是一个带上套套的iPhone
这是一个贴上钢化膜的带上套套的iPhone
在线网址:
打开网址可以在线编译哦!点击我吧!
选择edit:
之后点击submit :
参考书目:
- 设计模式之禅(第2版)作者:秦小波出版社:机械工业出版社
- 设计模式:Java版 作者:青岛东合信息技术有限公司出版社:电子工业出版社
- 大话设计模式 吴强 企业管理出版社
- Head First设计模式(中文版) [美] 弗里曼 中国电力出版社
- 菜鸟教程 https://www.runoob.com/design-pattern/decorator-pattern.html