一,简介
装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
二,角色
Component
定义一个对象接口,可以给这些对象动态的添加职责
ConcreteComponent
定义一个对象,可以给这个对象添加一些职责
Decorator
维持一个指向Component对象的指针,并定义一个与Component接口一致的接口
ConcreteDecorator
向组件添加具体的职责
三,举例
控制台打印如下表格,基本的姓名、年龄、学历、性别必须拥有,但是现在想动态的增加其他属性,而又不更改原代码。此处就可以用装饰模式,动态的添加一些额外的职责。
1,类图
2,代码
//定义抽象基类 (Component)
class Table {
public:
virtual void putTable() = 0;
};
//定义一个具体对象(ConcreteComponent)
class BaseTable :public Table {
public:
virtual void putTable() {
printf("姓名 \r\n");
printf("性别 \r\n");
printf("学历 \r\n");
printf("年龄 \r\n");
cout << "-------------------------" << endl;
}
};
//装饰抽象类 Decorator,用外类来扩展 Component的功能
class Decorator :public Table {
public:
Decorator(Table* concrateTb):m_pTable(concrateTb){}
virtual void putTable() {
m_pTable->putTable();
}
private:
Table* m_pTable;
};
class EngDcrt:public Decorator
{
public:
EngDcrt(Table* pTb):Decorator(pTb){}
virtual void putTable(){
printf("英语等级 \r\n");
Decorator::putTable();
}
};
class Experience :public Decorator
{
public:
Experience(Table* pTb) :Decorator(pTb) {}
virtual void putTable() {
printf("项目经验 \r\n" );
Decorator::putTable();
}
};
int main()
{
cout << "初始表格" << endl << endl;
BaseTable pro1;
pro1.putTable();
//扩展功能
cout << "新表格1" << endl << endl;
EngDcrt eng(&pro1);
eng.putTable();
//扩展功能
cout << "新表格2" << endl << endl;
Experience ex(&eng);
ex.putTable();
system("pause");
return 0;
}
四,优缺点
优点:
装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:
多层装饰比较复杂
五,使用场景
一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下使用扩展类,如 扩展一个类的功能或者动态增加功能,动态撤销。
如:孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。
注意事项:可代替继承