装饰( Decorator )模式又叫做包装模式。通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。
装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。
角色及职责
component
抽象产品类。是所有具体产品和装饰者的基类,客户端就是面向抽象产品类进行编程,他的指针和引用可以指向具体产品以及装饰者对象。–对应于案例中的Car。
ConcreateComponent
具体产品类,继承自抽象产品,装饰者可以对具体产品对象进行装饰添加其功能!通常来说,具体产品类继承了抽象产品类,需要实现相应的纯虚函数的功能,可以不含抽象产品类的指针或者引用–对应于案例中的Runcar。
Decorator
抽象装饰者。也是继承自抽象产品类,装饰者本身就是一个类,是一个具有某种功能的类,该类的构造函数通过注入一个产品对象,使得该产品对象具有更多的功能!这里说的产品对象一般面向抽象类编程。–这里给出的案例没有用到抽象装饰者,全部用的具体抽象者,这样解耦合做的不好,实际生产中,建议使用抽象装饰类,再实现具体装饰类,有利于解耦合和程序扩展。
ConcreateDecorator
具体装饰者,里面含有更具体的装饰功能,也就是更具体的新功能。–对应于案例中的SwimCar、FlyCar。
适用于:
装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。
案例
#include <iostream>
using namespace std;
/*增强一个类的功能
所增加的功能能够自由组合搭配--这一点单独靠继承做不到
多个类继承自同一个父类
父类有纯虚函数--用来增强功能
有一个类可以没有父类对象指针做成员变量
--》可以没有有参构造函数
--》在虚函数里可以不调用父类的虚函数,只实现最简单的功能
--》这个类的实例用来初始化客户端程序里的父类对象指针
--》其余的类都可以在他的基础上进行功能增强
其余子类都重写该纯虚函数,并在里面调用父类的虚函数
其余子类都有一个成员--父类对象的指针
其余子类的构造函数都会利用形参的父类指针初始化自己的父类指针成员
--》所有子类有参构造函数都用父类做参数是实现装饰模式的基础
*/
class Car//共同父类--抽象接口
{
public:
virtual void show() = 0;
};
/*最简单的基本功能类--能跑--初始化父类指针*/
class RunCar : public Car
{
public:
virtual void show()
{
cout<<"===================\n"<<"I can run"<<endl;
}
private:
//Car * m_car;//可以没有父类指针做成员变量
};
/*其余功能增强类--增加能游泳的功能--
* --在虚函数里调用父类虚函数实现功能增强--父类指针已被基本类实例初始化*/
class SwimCar: public Car
{
public:
SwimCar(Car * car)
{
m_car = car;
}
virtual void show()
{
m_car ->show();
cout<<"I can swiming"<<endl;
}
private:
Car * m_car;
};
/*其余功能增强类--增加能飞翔的功能--
* --在虚函数里调用父类虚函数实现功能增强--父类指针已被基本类实例初始化*/
class FlyCar:public Car
{
public:
FlyCar(Car * car)
{
m_car = car;
}
virtual void show()
{
m_car ->show();
cout<<"I can fly"<<endl;
}
private:
Car * m_car;
};
int main265()
{
/*父类指针*/
Car * mycar = NULL;
/*用基本类初始化父类指针*/
mycar = new RunCar;
mycar->show();
/*为已经具备run功能的父类实例
增加fly功能得到新的实例*/
FlyCar *fly = new FlyCar(mycar);
fly->show();
/*给前面得到的实例装饰新的swim功能*/
SwimCar *swim = new SwimCar(fly);
swim->show();
/*内存回收*/
delete swim;
delete fly;
delete mycar;
return 0;
}