什么是装饰者模式
装饰者模式动态地将责任附加到对象上。当需要扩展时,装饰者能提供比继承能有弹性的替代方案。当我们需要动态地添加一些功能时,可以使用装饰者模式。
举个例子
装饰者模式通过创建一个Component基类,然后让装饰者和被装饰者都继承这个基类。并在装饰者只中声明一哥被装饰者变量,从而识别要装饰的对象,并在自己的方法中,对被装饰者的方法进行功能添加。
现在我们有许多种咖啡,需要对这些咖啡添加配料,例如牛奶什么的,并且要计算咖啡和各种配料的花费。我们可以设计每种情况都设计成一个类,但是当我们的配料太多时,会发生类的爆炸,因为情况实在是太多了。装饰者模式正是合适的解决方案。
设计思想:
1、面向接口编程,而不是面向实现。我们不应该将每种搭配写死在类中。
2、对拓展开放,对修改关闭。我们应该支持之后功能的扩展,但是不允许修改我们现有的代码。
使用装饰者模式,每当我们需要一种配料时,就将对象做一层装饰,最终形成我们想要的功能。
#include <iostream>
#include <string>
using namespace std;
class Component{
public:
virtual int cost() = 0;
virtual string getDescription() = 0;
};
class BlackCoffee : public Component{
public:
int cost(){ return 3;}
string getDescription(){ return "BlackCoffe";}
};
class Decorator : public Component{
protected:
Component* wrappedObj;
// 如果要添加装饰类其他需要实现的方法,在此处声明
public:
Decorator(Component* Obj){ wrappedObj = Obj; }
virtual ~Decorator(){}
};
class Milk : public Decorator{
public:
Milk(Component* Obj):Decorator(Obj){}
int cost(){ return 2 + wrappedObj -> cost();}
string getDescription(){ return wrappedObj -> getDescription() + "Milk";}
~Milk(){
if(wrappedObj)
delete wrappedObj;
}
};
class Ice : public Decorator{
public:
Ice(Component* Obj):Decorator(Obj){}
int cost(){ return 1 + wrappedObj -> cost();}
string getDescription(){ return wrappedObj -> getDescription() +"Ice";}
~Ice(){
if(wrappedObj)
delete wrappedObj;
}
};
int main(){
Component* Coffee = new BlackCoffee();
Coffee = new Milk(Coffee);
Coffee = new Ice(Coffee);
cout << "menu is " << Coffee -> getDescription() << " ,cost is " << Coffee -> cost();
delete Coffee;
}
输出结果为:
menu is BlackCoffeMilkIce ,cost is 6
我们可以任意扩展新的配料,而不用更改现有的代码。在mian函数中,Coffee的生成也许有点笨拙,我们可以使用工厂模式或者生成者模式,来进行新的优化。