装饰模式: 动态的给一个对象添加额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
特点:
1. 装饰对象包含一个真实对象的引用,Decorator有一个Component的引用或者指针
2. 装饰对象和真实对象拥有相同的接口,这样客户端对象就可以和真实对象一样和装饰对象交互
使用场景:
需要动态的给一个类添加功能,这些功能还可以撤销
增加一些由基本功能的排列组合组成的大量的功能,继承关系不那么现实了,设计师可以创造出不同行为的组合
结构图:
component:定义一个对象接口,可以给这些对象动态添加职责
ConcreteComponent:具体的对象,也可以给这个对象添加职责
Decorator:核心类,装饰抽象类,继承了Component,对于Component来说无需知道Decorator的存在
ConcreteDecorator:具体的装饰对象,对Component添加职责的功能
好处:
有效的把类的核心职责和装饰功能区分开了,而且还可以去除相关类中重复的装饰逻辑。
装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何添加到对象链中。
具体应用实例:Avatar系统,一种在网络游戏或者论坛上中应用很广泛的纸娃娃系统
一个例子:穿衣服打扮自己
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
/*
服饰搭配问题
*/
/*component class*/
class person
{
private:
string name;
public:
person()
{ }
person(string name)
{
this->name = name;
}
virtual void show()
{
cout <<"name is "<<name<< endl;
}
};
/*decorator class*/
class clothes: public person
{
protected:
person *man;
public:
void decorate(person *man)
{
this->man = man;
}
void show() //override
{
if(man != NULL)
{
man->show();
}
}
};
/*concrete decorate class */
class T_shirt: public clothes
{
public:
void show()
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" T-shirt "<< endl;
}
};
class Big_trouser: public clothes
{
public:
void show()
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" Big-trouser "<< endl;
}
};
class Big_shoe: public clothes
{
public:
void show()
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" Big-shoe "<< endl;
}
};
class red_cat: public clothes
{
public:
void show() //core part
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" red-cat "<< endl;
}
};
class glovers: public clothes
{
public:
void show()
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" glovers "<< endl;
}
};
class black_bag: public clothes
{
public:
void show()
{
man->show();
add_behavior();
}
void add_behavior()
{
cout <<" black-bag "<< endl;
}
};
int main()
{ string name("xiaoming");
person *xp = new person(name);
T_shirt *Ts = new T_shirt();
black_bag *bb = new black_bag();
glovers *gl = new glovers();
red_cat *rc = new red_cat();
Ts->decorate(xp);
bb->decorate(Ts);
gl->decorate(bb);
rc->decorate(gl);
rc->show();
system("pause");
return 0;
}
/*
name is xiaoming
T-shirt
black-bag
glovers
red-cat
*/