作用
为现有类增加功能
案例说明
class Car
{
public:virtual void show()=0;
};class Bmw:public Car
{
public:void show(){cout<<"宝马汽车>>"<<endl;}
};class Audi:public Car
{
public:void show(){cout<<"奥迪汽车>>"<<endl;}
};class Bcw:public Car{
public:void show(){cout<<"奔驰汽车>>"<<endl;}
};
如上,我们定义了汽车抽象类,并定义三个具体的汽车类。
现在的问题是:如果需要给这三种汽车都增加仨个功能——定速导航、刹车、车道偏离。应该如何实现?
- 第一种办法,为每个汽车类都定义两个功能子类,如下图所示
- 第二种办法,使用装饰器,只需要给Car下增加一个功能类
class CarFunction:public Car{
public:CarFunction(Car* carPtr):_carPtr(carPtr){};
protected :Car* _carPtr;
};
//装饰器1,定速导航
class ConcreteDecorator:public CarFunction
{
public:ConcreteDecorator(Car* carPtr):CarFunction(carPtr){};void show(){_carPtr->show();cout<<"\t定速巡航"<<endl;}
};//装饰器2,刹车
class BrakeDecorator:public CarFunction
{
public:BrakeDecorator(Car* carPtr):CarFunction(carPtr){}void show(){_carPtr->show();cout<<"\t刹车"<<endl;}
};//车道偏离
class LaneDecorator:public CarFunction
{
public:LaneDecorator(Car* carPtr):CarFunction(carPtr){}void show(){_carPtr->show();cout<<"\t车道偏离"<<endl;}
};
代码测试
void test()
{Car* p1=new ConcreteDecorator(new Bmw());//使用宝马汽车定位导航功能Car* p2=new BrakeDecorator(new Audi());//使用奥迪汽车请假刹车功能Car* p3=new LaneDecorator(new Bcw());//使用奔驰汽车车道偏离功能p1->show();p2->show();p3->show();
}
可以看到,使用装饰器模式给类增加功能的优点就是避免了大量的代码重复,假如使用继承子类的方式给各种汽车类增加功能,这种重复的功能增加会产生大量冗余的代码
对比代理模式(详见c++设计模式之代理模式-CSDN博客),装饰器模式和代理模式的设计都有许多相似之处
他们都通过将真实的对象包装到代理类和装饰类中,或者说把实际的操作对象放到代理类或装饰类中来达成目的。他们利用的特性都是基于c++的多态特性。
但他们的目的不同
- 代理模式主要是为了控制对真实对象的访问
- 装饰器模式主要是为了给真实对象增加功能