定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活
类型:结构型模式
类图:
四大组件:
1、抽象组件类Component,这个类可以是抽象类或者是接口类(建议抽象类),它为子类提供了行为的标准接口,子类根据自身情况实现自己的行为,这里将要发的继承并不是为了继承行为,而是为了使具体组件(被装饰)与装饰者的类型相互匹配,所以通过继承的方式,利用赋值兼容性原则来达到类型的匹配
2、具体组件类ConcreteComponent,被装饰类,这个类的对象将会被装饰者类动态的添加职责
3、抽象装饰者类Decorator,这个类可以是抽象类或者是接口类,但最好是抽象类,并在这个类中持有Component指针或引用,这样的话,当扩展新的具体装饰者类时,会减少很多工作量
4、具体装饰者类ConcreteDecorator,按自身的特点实现类中定义的行为标准接口,并按需求添加适合自身特点的属性,这些属性与行为将来会给具体组件类ConcreteComponent带去新的职责
实现代码:
#include <iostream>
#include <string>
class Car
{
public:
virtual void Show() = 0;
virtual ~Car(){};
};
class Impreza : public Car
{
private:
std::string CarName;
public:
explicit Impreza() : CarName(" impreza ")
{
}
void Show()
{
std::cout << CarName << std::endl;
}
};
class Decorator : public Car
{
protected:
Car *car;
public:
explicit Decorator(Car *car) : car(car)
{
}
virtual ~Decorator(){};
};
class Decals : public Decorator
{
private:
std::string color;
public:
Decals(Car *car, std::string color) : Decorator(car), color(color)
{
}
void Show()
{
std::cout << color << " Decals, ";
if( NULL != car )
{
car->Show();
}
}
};
class BodyKit : public Decorator
{
public:
explicit BodyKit(Car * car) : Decorator(car)
{
}
void Show()
{
std::cout << " Body Kit, ";
if( NULL != car )
{
car->Show();
}
}
};
class Empennage : public Decorator
{
private:
int *Len;
public:
Empennage(Car *car, int len) : Decorator(car)
{
Len = new int(len);
}
void Show()
{
std::cout << *Len << " meters Empennage,";
if( NULL != car )
{
car->Show();
}
}
~Empennage() //装饰者与被装饰者是独立的,装饰者仅需要销毁自己就好了,不应该有销毁被装饰对象的能力
{
delete Len;
std::cout << "Demount Empennage" << std::endl;
}
};
int main(int argc, char *argv[])
{
Car *car = new Impreza();
car->Show();
Decorator *decorator1 = new Decals(car, "Read");
Decorator *decorator2 = new BodyKit(decorator1);
Decorator *decorator3 = new Empennage(decorator2, 2);
decorator3->Show();
delete decorator3;
delete decorator2;
delete decorator1;
delete car;
system("pause");
return 0;
}
为了delete父类指针时能顺利析构子类部分,我们应该把父类的析构函数定义为virtual的,也就是说在这里类Component的析构函数应该是virtual的,如果其还要是接口类的话,为满足接口类定义,我们还必须将virtual的析构函数声明为纯虚函数,但这还没完,由于析构函数工作时的特殊性,我们必须还要为其定义一份实现,即使这个实现是空的,否则连接器会报错。于是我们还得为它提供一份空实现。这真的是比较麻烦的事情,所以使用抽象类会更好一些(对装饰者类来说,这个还不够明显,对之前我们说到的工厂模式来说,将基类的析构函数定义为virtual就很有必要了)
优缺点:
优点:
1、使用装饰者来扩展职责比起继承来有更多的灵活性
2、不改变源码的情况下就可以动态的扩展对象
缺点:
1、会导致设计许多小类被设计出来,增加了程序的复杂度
2、在同一对象上使用过多装饰者会造成性能的
适用场景:
1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
3、当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时
C++中接口类的标准定义
1、类中不含任何成员变量
2、所有成员函数都是公有的
3、所有成员函数都是纯虚函数