背景
有一个咖啡馆有
单品咖啡:意大利浓咖啡、美式咖啡、无因咖啡
调料:牛奶、巧克力
点单时需要点一个单品咖啡,可以选择加调料或者不加。
最后计算价格。
较好的传统思路:
创建一个抽象的咖啡类,其中有各个调料的对象,为每个对象配备添加方法。
创建各个单品咖啡类,继承自抽象咖啡类。
在点单时,只要声明一个单品咖啡,再通过单品咖啡的内置方法添加调料。
问题:
在增加或者删除种类时,代码维护量很大。
耦合度较高,不符合开闭原则
基本介绍
动态地将功能附加到对象上
四个角色
①Component抽象类:所有的装饰物品,被装饰物品的抽象
②被装饰者:被装饰的物品(例子中的单品咖啡)
③装饰物抽象类:装饰被装饰的抽象类(例子中的所有调料的抽象)
④具体装饰物:继承自装饰物抽象类(例子中的具体调料)
装饰物和被装饰者都继承自Component抽象类,
具体装饰物继承自装饰物抽象类,
为了方便管理,在装饰物抽象类中声明一个被装饰者对象。
具体实现
创建最大的抽象类Drink类,有描述属性,计算价格方法。
分别创建所有的单品咖啡类继承自Drink类(如果咖啡种类很多,可以做一个抽象咖啡类作为缓冲层)
创建调料抽象类,在这个类中声明一个Drink类对象,但是这个类依然继承自Drink类。
在这个类中的计算价格方法时Drink类对象的价格+自身价格。
分别创建所有调料类,继承自调料抽象类
举个具体例子:
在这个模式下的订单:2份巧克力+一份牛奶的黑咖啡
巧克力
{
巧克力
{
牛奶
{
黑咖啡
}
}
}
黑咖啡作为一个Drink类对象被声明在牛奶类对象中,
而这个牛奶类对象又被作为Drink类对象声明在巧克力类对象中,
同理,这个巧克力对象又被包裹在另一个巧克力对象中。
在计算价格时,我们调用最外面的巧克力对象的计算价格方法,
在这个方法中调用的是下一层巧克力对象的计算价格方法+一份巧克力的价格
那么下一次巧克力对象的计算价格方法是牛奶的计算价格方法+一份巧克力的价格。
同理,知道计算到黑咖啡的价格时,不再是两项相加的价格,递归结束。
最后的价格就是黑咖啡的价格+一份牛奶的价格+一份巧克力的价格+一份巧克力的价格。
在使用时:
new一个具体的单品咖啡类对象,
如果有调料,就new一个具体的调料类对象,
把单品咖啡对象传入调料对象的Drink属性内,
如果还要加调料,
就可以再new一个具体调料类对象,把前面的调料类对象传入这个对象内。
调用最后一个调料对象类的计算价格方法,算出最后的价格。