1、decorator(装饰)
(1)意图
动态的给以个对象添加一些额外的职责。就增加功能而言,decorator模式生成子类更加灵活。
(2)结构
componet定义一个对象的接口,可以给这些对象动态的添加职责
concretecomponet定一个对象,可以给这个对象添加职责
decorator维持一个指向component对象的指针,并定一个与component接口一致的接口
concretedecorator想组组建添加职责
(3)适用性
在不影响其他对象的情况下,以动态、透明的方式给单位的对象添加职责
处理哪些可以撤销的职责。
当不能采用生成子类的方式进行扩充时候,一种情况是,可能有大量的独立扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长,另一种情况可能是由于定义被隐藏,或类定义又用于生成子类。
2、根据UML编写代码
根据对代uml图的展示,该uml主要涉及2个关系,一个是泛化关系一个是关联关联(聚合)
(1)泛化关系
该关系用在父类与子类的之间,比如component为decorator的父类,后者为前者的子类。
(2)关联关系
decorator与component之间保持关联关系,即在decorator中生成一个"component*"的指针用于对传入的component类及子类进行操作。
(3)UML框架解析
我们通过component下的concretecomponent对我们想要的效果进行一个实际的操作,然后在通过decorator的子类对concretecomponent的operation的结果进行补充或者删除。
(4)代入生活举例
假如整个uml图是一个牛肉面馆,concretecomponent(点餐员)对着component(后厨)客人点了一碗牛肉面(concretecomponent->operation()),同时对后厨说客人提了特殊要求(decorator)希望多加点香菜(concretedecoratorA)和少放点辣椒(concretedecoratorB)
3、代码实现
#include<iostream>
using namespace std;
class component{//服务人员
public:
virtual void opreation()=0;
};
class concretecomponent:public component{//服务员将客人的需求报告给后厨,并只做一碗普通的牛肉面
public:
void opreation(){
cout<<"客人点了一碗牛肉面"<<endl;
}
};
class decorator:public component{//客人的特殊需求
public:
virtual void opreation(){};
component *p;//形成一个指针方便对普通的牛肉面并进行一些操作
};
class concretedecoratorA:public decorator{
public:
concretedecoratorA(component *p){
decorator::p=p;//this=>p=p;
}
void opreation(){
p->opreation();//执行之前的职责
cout<<"请多加香菜"<<endl;//增加职能
}
};
class concretedecoratorB:public decorator{
public:
concretedecoratorB(component *p){
decorator::p=p;//this=>p=p;
}
void opreation(){
p->opreation();
cout<<"少放辣椒"<<endl;//减少职能
}
};
int main(){
component *noodle =new concretecomponent();//客人点了一碗牛肉面
noodle=new concretedecoratorA(noodle);//代码核心所在,在牛肉面的基础上添加客人的特殊需求1,形成一碗新的牛肉面
noodle=new concretedecoratorB(noodle);//在新的牛肉面的基础上再添加客户一个特殊需求后,形成一个最终的牛肉面
noodle->opreation();//把满足客户所有需求的牛肉面端上桌
return 0;
}
特别注意一个地方,一碗牛肉面不可能都做好了,放在客人桌上了再给客人加香菜和少放辣椒,原则上应该一次性弄好端到客人桌子上,程序中用 noodle->opreation()这一行代码一次性实现了所有的操作。noodle->opreation()这行代码中的这个noodle到底是啥样子的?经过我们的无数次套娃,其实他是这样子:
noodle=new concretedecoratorB(new concretedecoratorA( new concretecomponent() );
我在执行opreation() 程序会从最里面的 new concretecomponent() 从内到外一层一层反向执行。
如果上诉代码实在难以理解我们换个方式:
int main(){
component *noodle =new concretecomponent();
component *noodle1 =NULL;
component *noodle2 =NULL;
noodle1=new concretedecoratorA(noodle);
noodle2=new concretedecoratorB(noodle1);
noodle2->opreation();
return 0;
}