1 概述
装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。有时我们希望给某个对象而不是整个类添加一些功能。比如有一个电脑(人),允许你为电脑添加特性,比如添加键盘、鼠标垫等(穿衣服)。一种灵活的设计方式是,将电脑(人)嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。下面给出装饰模式的UML图。
- Component是定义一个对象接口,可以给这些对象动态的添加职责
- ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责
- Decorator抽象装饰类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无序知道Decorator的存在的
- ConcreteDecorator是具体的装饰类,起到给Component添加职责的功能
- 如果只有一个ConcreteComponent类而没有抽象的类,那么Decorator可以是ConcreteComponent的一个子类。
- 同样,如果只有一个ConcreteComponent类,那么没有必要建立一个单独的Decorator 类,而可以把Decorator和ConcreteComponent的责任合成一个类
- 装饰的方法是:首先用ConcreteComponent实例化一个对象C,然后用ConcreteComponentA实例化一个对象d1来包装 C,再用ConcreteComponentB实例化一个对象d2来包装 d1,最后执行d2的Operation()
2 电脑配件实现
在这种设计中,电脑(人)的装饰功能被独立出来,可以单独发展,进而简化了具体电脑类的设计。下面给出类的实现:
//公共抽象类
class Computer
{
public:
Computer() {
}
virtual ~Computer() {
}
virtual void ShowDecorate() {
}
};
//具体的电脑类
class DellComputer : public Computer
{
private:
string m_name; //电脑名称
public:
DellComputer(string name): m_name(name){
}
~DellComputer() {
}
virtual void ShowDecorate() {
cout<<m_name<<"的装饰"<<endl;}//virtual可写可不写
};
//装饰类
class DecoratorComputer : public Computer
{
private:
Computer *m_computer; //要装饰的手机
public:
DecoratorComputere(Computer *m_computer): m_computer(computer) {
}
virtual void ShowDecorate() {
m_computer->ShowDecorate(); }
};
//具体的装饰类
class DecoratorA : public DecoratorComputer
{
public:
DecoratorA(Computer *m_computer) : DecoratorComputer(computer) {
}
void ShowDecorate() {
DecoratorComputer::ShowDecorate(); AddDecorate(); }
private://本类独有的方法,以区别其他具体装饰类
void AddDecorate() {
cout<<"增加挂件1"<<endl; } //增加的装饰
};
//具体的装饰类
class DecoratorB : public DecoratorComputer
{
public:
DecoratorB(Computer *m_computer) : DecoratorComputer(computer) {
}
void ShowDecorate() {
DecoratorComputer::ShowDecorate(); AddDecorate(); }
private:
void AddDecorate() {
cout<<"增加挂件2"<<endl; } //增加的装饰
};
首先用DellComputer实例化一个对象computer,然后用DecoratorA实例化一个对象dpa来包装 computer,再用DecoratorA实例化一个对象dpb来包装 dpa,最后执行dpb的ShowDecorate()
int main()
{
Computer *computer = new DellComputer("xxxx");
Computer *dpa = new DecoratorA(computer); //装饰,增加挂件1
Computer *dpb = new DecoratorB(dpa); //装饰,增加挂件2
dpb->ShowDecorate();
delete dpa;
delete dpb;
delete computer;
return 0;
}
3 人穿衣搭配代码实现
下面的例子是一个人搭配穿衣的问题,因为只有一个ConcreteComponent类(只有一个具体的人:xiaocai)而没有抽象的类,所以把Decorator看作ConcreteComponent的一个子类。
#include <iostream>
using namespace std;
class Person{
public:
Person(){
}
Person(string name){
this->m_name = name;
cout << "我是" << m_name << endl;
}
virtual void show(){
}
virtual ~Person(){
}
private:
string m_name;
};
//服饰类(装饰器)
class Finery:public Person{
protected:
Person *component;
public:
void Decorate(Person *component){
this->component = component;
}
virtual void show(){
component->show();
}
};
//具体服饰类
class TShirts:public Finery{
public:
virtual void show(){
Finery::show();//为什么与下句顺序翻一下就不可以
cout << "大体恤 " << endl;
}
};
//具体服饰类
class Sneakers:public Finery{
public:
virtual void show(){
Finery::show();
cout << "球鞋 " << endl;
}
};
//具体服饰类
class BigTrouser:public Finery{
public:
virtual void show(){
Finery::show();
cout << "垮裤 " << endl;
}
};
int main(){
Person* xc = new Person("xiaocai");
cout << "第一种装扮:" << endl;
Sneakers* pgx = new Sneakers();
BigTrouser* kk = new BigTrouser();
TShirts *dtx = new TShirts();
pgx->Decorate(xc);
kk->Decorate(pgx);
dtx->Decorate(kk);
dtx->show();
return 0;
}
具体服饰类中
virtual void show(){
Finery::show();//为什么与下句顺序翻一下就不可以
cout << "大体恤 " << endl;
}
为什么与下句顺序翻一下就不可以?
首先运行Finery::show(),再运行本类功能cout << “大体恤” << endl;相当于对原来的Finery进行了装饰。