运行时扩展,比编译时继承威力更大
装饰对象,给爱用继承的人一个全新的设计眼界
星巴兹(Starbuzz)咖啡订单系统1
(实锤了 是我买不起的样子)
星巴兹咖啡的扩张速度太快了,他们准备更新订单系统
他们之前设计的类是这样的
// 饮料类,店内所有饮料继承此类
abstract class Beverage{
// 咖啡店的宣传标语
String description;
public void getDesString() {
System.out.println(this.description);
}
// 咖啡的花销,子类自己实现
public abstract void cost();
}
由于购买咖啡的时候会加入很多调料,比如牛奶、椰果等等,这样就组成了很多不同的咖啡种类,价格也就不一样
一旦调料多起来,类设计就会变成这样:
类爆炸!这简直是维护噩梦,如果牛奶价格上涨,所有加了牛奶的咖啡种类的
cost()
都要重写,这可太刺激了
利用实例变量和继承
为了不出现类爆炸的情况,我们使用实例变量和继承,在基类Beverage
种添加代表每种调料的boolean
类型实例变量
子类的
cost()
会在自己的花费上,判断是否有各个调料,有的话将调料的价格加上去
这会出现这样的问题:
- 调料价钱的改变会使我们改变现有代码
- 一旦出现新的调料,就要加上新的方法,并改变超类种的
cost()
方法 - 比如,对于热咖啡来说,加”冰“这个调料是完全没必要的,但是热咖啡还是继承了
hasIce()
这个方法 - ……
认识装饰者模式
- 设计原则:类应该对扩展开放,对修改关闭
我们了解到,利用继承无法完全解决问题,在星巴兹我们遇到的问题有:类爆炸、设计死板、基类加入新功能并不适用于所有子类
我们可以这样做:以饮料为主体,之后在运行过程中用调料来“装饰“(decorate
)它,比如顾客想要摩卡咖啡
- 拿一个深焙咖啡(
DarkRoast
)对象 - 加入摩卡(
Mocha
),我们称之为以摩卡对象装饰它 - 调用
cost()
方法,并依赖委托(delegrate)将调料的钱加上去
以装饰器构造饮料订单
- 首先准备一个深焙咖啡(
DarkRoast
)对象