装饰模式:动态地给一个对象添加一些额外的功能,使之更加灵活地实现扩展的功能,并且以比生成子类更少的成本来实现功能。
应用场景:当一个类需要新的功能的时候(如为QQ头像穿上装扮),在不修改原有代码而只以扩展代码的方法来实现,增加的新功能像穿衣服一样:1、穿不穿衣服,class'人'都不受影响;2、穿衣服的方法由衣服来实现;3、特别注意新衣服(新功能)的执行顺序:先穿鞋子再穿袜子就出现问题了(例:先备份了数据再删除垃圾文件)。
//该类是基类,主体功能类继承该类实现原有主体功能,装饰器继承该类实现扩展装饰的功能
class base_component
{
public:
virtual void func();
}
//实现原有功能的类(即被装饰器添加功能的对象)
class component:base_component
{
public:
void func() override //该函数是完成功能的主体
{
std::cout<<"do something"<<std::endl;
}
}
//该类是装饰器的抽象基类,它确定了所有装饰器的接口和属性
class decorator:base_component
{
protected:
base_component comp;//用于指向被装饰的实体;
public:
void decorate(base_component& component)//设置要将本类装饰到哪一个类
{
this.comp = component; //指向被装饰实体;
}
void func() override
{
base_component::func();//调用父类的方法,完成父类的(原有的、本次装饰之前已有的)功能
}
}
//装饰器A实现新增的功能
class decorator_A:decorator
{
public:
void func() override
{
//do_new_func1();
decorator::func(); //调用父类的方法,完成父类原有的、该装饰器之前已有的功能
}
}
class decorator_B:decorator
{
public:
void func() override
{
// do_new_func2();
decorator::func(); //调用父类的方法,完成父类原有的、该装饰器之前已有的功能
}
}
//客户端
class foo
{
void main()
{
component bar=new component; //系统的主体,装饰器的作用对象实例
//装饰器
decorator_A dec1 = new decorator_A();
decorator_B dec2 = new decoratot_B();
//执行装饰动作(即将装饰器安装到作用对象),但此时没有开始执行任何任务(包括新增的功能和原有功能)
dec1.decorate(component);//为系统主体增加dec1所实现的功能
dec2.decorate(dec1); //将增加了dec1之后的对象作为一个整体,在此基础上再加一个功能;
//注意:这里装饰器的安装顺序就体现了装饰模式的顺序控制,使得客户端能够轻松安排新增的功能的顺序;
dec2.func(); //所有装饰器安装完成后,从dec2开始启动整个系统的运行:注意,后面添加的新功能会首先执行;
}
}
代码总结:装饰器的decorate方法指示该装饰器所提供的新功能是给哪个实体使用的,细节表现为:1、与实体继承了相同的基类,装饰器对象实例与原有类实例在互相独立的情况下完成新增的功能,装饰对象甚至不知道有装饰器对象实例为它完成了新增的功能;2、decorate方法实际上只是提供连接:将装饰器对象与原有类对象连接起来,新增的功能由装饰器的func()方法实现,并由该方法调用基类的func()方法,使得装饰器新增的功能完成后能够转到基类去执行原有的功能(实质是当前装饰器之上的各个装饰器提供的功能和系统原有实现的功能)。装饰模式总结:装饰模块能够动态地灵活地添加各种功能。'动态'体现在客户端能够自主地在自己的有限的类对象实例中完成各种附加功能或零散功能的组合;灵活体现在增加新功能的时候,对已有代码的修改几乎为0,仅需扩展可重用的代码即可实现功能的动态。