一、装饰模式:
——动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
一个人穿衣服,无论鞋子、衬衫、裤子其实都可以理解为对人的装饰。通过服装的搭配可以产生大量不同着装的人,这时用继承不太好实现。
//人类
class Person {
public:
Person Person(const string &name) {m_name = name;}
virtual void show()
{
cout << "装扮的" << m_name;
}
};
//服饰类:
class Finery : public Person {
protected:
Person *component;
public:
void decorate(Person *comp)
{
component = comp;
}
void show()
{
if (component !=nullptr) {
component->show();
}
}
//具体服饰类
class TShirts : public Finery {
public:
void show()
{
cout << "T恤";
Finery::show();
}
}
class BigTrouser : public Finery;
class Sneakers : public Finery;
//使用
Person *person = new Person("小帅");
Sneakers *sk = new Sneakers;
BigTrouser *bt = new BigTrouser;
TShirts *ts = new TShirts;
sk.decorate(person);
bt.decorate(sk);
ts.decorate(bt);
ts.show();
TShirts 类ts使用TShirts::show方法,在该方法内实现了自己的功能(输出),还调用了直接基类的虚函数版本Finery::show,通过实例化时传进来的component指针(Person类指针指向了BigTrouser类的person基类部分)调用了BigTrouser类的BigTrouser::show方法。BigTrouser类和Sneaker类的show方法也是如此,直到执行Person::show方法。
于是,cout输出为是:“T恤 垮裤 球鞋 装扮的小帅”,
装饰模式就是为已有功能动态地添加更多功能得到一种方式。
当系统中需要新功能时,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。但这种做法的问题在于,在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。而这些新加入的东西仅仅是为了满足一些只在某些特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。像穿衣服一样,可以全副武装,也可以一丝不挂。
装饰模式地优点就在于,把类中的装饰功能从类中移除,简化原有的类。
这样做更大的好处在于,有效地把类中的核心职责和装饰功能区分开,去除重复的装饰逻辑。