装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的,至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。
装饰模式是为已有功能动态的添加更多新的功能的一种方式。
应用场景:当系统需要需要新的功能的时候,是向就得类中添加新的代码,比如你又买了一件衣服,就可以重新添加一个衣服的类。这些新添加的代码通常装饰了原有类的核心职责或主要行为,如果在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂性,而这些新添加的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要,而装饰模式却提供了一个非常好的解决方案,把每个要装饰的功能放在单独的类中,并让这个类包装所要修饰的对象,因此,当需要执行特殊任务时,客户代码就可以在运行时根据需要有选择的,按顺序的装饰功能包装对象(注意,顺序不唯一)。
优点:把类中装饰功能从类中搬移出去,这样就可以简化原有的类,吧类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
区别:这个模式和建造者模式似乎有点相似,但是注意,建造者模式过程可以固定的,如果是建造者模式,穿衣服这个过程视为一个抽象基类,里面有两步,穿上衣穿下衣,然后穿运动服和西装是两个具体建造实例,不会出现程序里那种自由组合的现象,出现了穿T恤和西裤这种尴尬的组合。
#include <string>
#include <iostream>
using namespace std;
class Person//被装饰的对象的基类
{
public:
virtual void show() = 0;//核心职责,当然是展示自己
};
class ChinaPerson : public Person
{
private:
string name;
public:
ChinaPerson(string _name) :name(_name)
{}
void show()
{
cout << "装饰的是" << name << endl;
}
};
class Finery : public Person//服饰类,来装饰Person,共有继承总感觉怪怪的
{
protected:
Person* component;//需要被装饰的人
public:
void Decorate(Person* component)
{
this->component = component;
}
void show()
{
if (component != nullptr)
{
component->show();//装饰Perosn
}
}
};
class TShirts : public Finery//具体服饰类,穿T恤
{
public:
void show()
{
Finery::show();
cout << "大T恤" << endl;
}
};
class BigTrouser : public Finery//具体服饰类,穿垮裤
{
public:
void show()
{
Finery::show();
cout << "垮裤" << endl;
}
};
class ManSuit : public Finery
{
public:
void show()
{
Finery::show();
cout << "穿西服" << endl;
}
};
class WestTrouser : public Finery
{
public:
void show()
{
Finery::show();
cout << "穿西裤" << endl;
}
};
int main()
{
Person* p = new ChinaPerson("小李");
TShirts* ts = new TShirts();
BigTrouser* bt = new BigTrouser();
ManSuit* ms = new ManSuit();
WestTrouser* wt = new WestTrouser();
ts->Decorate(p);
bt->Decorate(p);
ms->Decorate(p);
wt->Decorate(p);
cout << "第一种装扮" << endl;
ts->show();
bt->show();
cout << "第二种装扮" << endl;
ms->show();
wt->show();
cout << "第三种装扮" << endl;
ts->show();
wt->show();
delete p;
delete ts;
delete bt;
delete ms;
delete wt;
}