介绍
装饰模式可以动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更加灵活。例如,一个图形界面用户工具箱允许你对任意一个用户界面组件添加一些特性,如边框,或者是一些行为,如窗口滚动,可以使用继承,但是使用装饰模式更好。
例子:本文我们考虑这样一个情况,我们买奶茶时有不同种类的奶茶(red green),还有不同温度的奶茶。
设计模式参与者:
- Component 定义一个对象接口,可以给这些对象动态的添加职责
- Decorator 维持一个指向Component 对象的指针,并定义一个与Component 接口一致的接口
- ConcreteComponent 定义一个对象,可以给这些对象动态的添加职责
- ConcreteDecorator 具体的组件实现具体的职责
实现代码
class Tea{//Component 定义一个对象接口,可以给这些对象动态的添加职责
public:
virtual void showInfo(){
}
};
class TeaDecorator:public Tea {//维持一个指向Component 对象的指针,并定义一个与Component 接口一致的接口
public:
TeaDecorator(Tea *tea):_tea(tea){}
void showInfo() override
{
_tea->showInfo();
}
private:
Tea *_tea;
};
class TeaType : public TeaDecorator{//具体的组件实现具体的职责
public:
TeaType(Tea *tea,std::string teaType,int price):
TeaDecorator(tea),
_teaType(teaType),
_price(price){}
void showInfo()
{
TeaDecorator::showInfo();
std::cout<<"Type : "<<_teaType<<", Price is "<<_price<<" ";
}
private:
std::string _teaType;
int _price;
};
class TeaTemperature : public TeaDecorator{//具体的组件实现具体的职责
public:
TeaTemperature(Tea *tea,int teaTemperature ,int price):
TeaDecorator(tea),
_teaTemperature (teaTemperature ),
_price(price){}
void showInfo()
{
TeaDecorator::showInfo();
std::cout<<"Temperature : "<<_teaTemperature <<", Price is "<<_price<<" ";
}
private:
int _teaTemperature ;
int _price;
};
int main()//客户端调用
{
auto *tea = new Tea();
TeaType *teaType = new TeaType(tea,"Red ",12);
teaType->showInfo();
std::cout<<std::endl;
auto *teaTemperature = new TeaTemperature(tea,60,13);
teaTemperature->showInfo();
std::cout<<std::endl;
auto *teaType1 = new TeaType(teaTemperature,"Green ",18);
teaType1->showInfo();
std::cout<<std::endl;
};
输出结果
Type : Red , Price is 12
Temperature : 60, Price is 13
Temperature : 60, Price is 13 Type : Green , Price is 18
可以看到利用装饰模式,我们将不同组件的所有信息都打印出来了。
优缺点
- 比静态继承更加灵活
- 避免在层次结构高层的类有太多的特征
- Decorator与其他的Component不一样,Decorator说一个透明的包装。
- 有许多小对象
参考
《设计模式:可复用面向对象软件的基础》