装饰器模式(Decorator Pattern):允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
装饰者模式适用场景:
(1)以动态的方式给对象添加职责。
(2)处理那些可以撤销的职责。
(3)当采用生成子类的方法进行扩充时,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
(1)抽象组件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
(2)被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体对象。
(3)装饰者组件(Decorator):持有组件对象的实例引用,该类的职责就是为了装饰具体组件对象,定义的基类。
(4)具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能。
装饰者模式实现步骤:
1.增强类与被增强类实现同一接口
2.增强类里面得到被增强类的引用(只要在增强类里面传入被增强类对象的一定就是装饰者模式)
3.对于不需要改写的方法,调用被增强类原有方法,对应需要改写增强的方法写自己的逻辑
下面就以一杯奶茶说起,我最喜欢喝大杯阿水茶的珍珠奶茶,可是有时候也会不满足奶茶只有珍珠,在天气热的时候我还要加冰块,心情好的时候再加个椰果等,这些其实都是对奶茶的拓展即装饰。
我们先来创建一个奶茶的抽象类,相当于Component
class Milk_Tea
{
public:
virtual void request(){};
};
再写一个珍珠奶茶类,相当于被装饰者
class Milk_Tea
{
public:
virtual void request(){};
};
然后实现装饰类:
class Decorator:public Milk_Tea {
protected:
Milk_Tea *milkyTea;
public:
Decorator(Milk_Tea *a){
milkyTea=a;
}
virtual void request(){
milkyTea->request();
}
};
分别写出不同装饰具体类:
class Add1:public Decorator {
public:
Add1(Milk_Tea *a):Decorator(a){
}
void request() {
milkyTea->request();
add_ice();
}
void add_ice(){
cout<<"天好热啊,老板我想加个冰。。。"<<endl;
}
};
class Add2:public Decorator {
public:
Add2(Milk_Tea *a):Decorator(a){
}
void request(){
milkyTea->request();
add_fruit();
}
void add_fruit(){
cout<<"再加个椰果,谢谢。。。"<<endl;
}
};
客户端:
int main()
{
Milk_Tea *m1=new Bubble_Tea();
Decorator *m2=new Add1(m1);
Decorator *m3=new Add2(m2);
m3->request();
return 0;
}
效果:
优点:
1、目的在于扩展对象的功能。装饰者模式提供比继承更好的灵活性。装饰是动态的,运行时可以修改的;继承是静态的,编译期便已确定好。
2、通过使用不同的装饰类及对他们的排列组合,可以创造出许多不同行为的组合。
缺点:
1、 产生很多的小对象,大量的小对象会占用内存。
2、 组合方式很多,很容易出错。