装饰模式:动态的将责任附加到对象上。
特点:1、采用组合的方式。2、装饰者和被装饰者都具有同样的超类。
缺点:1、会产生很多的小类,代码看起来会比较复杂。
通过上面的描述,装饰者模式应该具有四种类型的类:
一、超类。是装饰者和被装饰者都要继承的基类。
二、具体的被装饰者类。
三、抽象的装饰者。
四、具体的装饰者。
下面以奶茶店的奶茶来进行描述:
首先,我们定义一个超类,来描述这个奶茶具有的通用特性。
1、奶茶需要卖的价格。 2、是何种类型的奶茶。
class TeaMilk
{
string getTeaMilkDescription(); //比如是水果奶茶,牛奶奶茶等。
virtural double cost() = 0; //这个奶茶需要卖多少
};
2、具体的被装饰类 。定二个具体的类,一个为水果奶茶,一个为牛奶奶茶
class FruitsTeaType :public TeaMilk
{
public:
FruitsTeaType();
~FruitsTeaType ();
string getTeaMilkDescription(); //描述
double cost(); //价格
};
class MilkTeaType : public TeaMilk
{
public:
MilkTeaType();
~MilkTeaType();
string getTeaMilkDescription(); //描述
double cost(); //价格
}
3、装饰的抽象类。 这个抽象类,主要是用来动态绑定,由父类指向不同的子类。
class CondimentDecorator : public TeaMilk
{
virtual string getTeaMilkDescription(); //描述
};
4、具体的装饰者. 比如给奶茶加 柠檬(lenmon),加奶油(whip)等
class Lenmon : public CondimentDecorator
{
public:
Lenmon(TeaMilk *tea); //注意,构造类需要传入需要装饰的对象。
~Lenmon();
string getTeaMilkDescription(); //描述
double cost(); //价格
}
//注意在实现的时候,一定要先获取传入的装饰者对象,然后在装饰者的基础上进行增加。
class Whip : public CondimentDecorator
{
public:
Whip (TeaMilk *tea); //注意,构造类需要传入需要装饰的对象。
~Whip ();
string getTeaMilkDescription(); //描述
double cost(); //价格
}
示例显示
int main()
{
TeaMilk *fruitsType = new FruitsTeaType(); //水果类型的奶茶。
MilkTeaType *milkType = new MilkTeaType(); //牛奶类型的奶茶
//加了奶油的水果茶价格
TeaMilk *fruitsWhip = new Whip(fruitsType );
furitsWhip.cost(); //水果奶油茶价格
//加了奶油和柠檬的水果茶价格
TeaMilk *allFruits = new Lenmon (fruitsWhip );
allFruits.cost(); //加了奶油和柠檬的价格
return 0;
}