装饰者模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。假如设计一个咖啡店的订单系统,咖啡有很多种,比如:HouseBlend,DarkRoast,Decaf 等等,同时,可以在咖啡里面加入很多调料,比如:豆浆(Soy),摩卡(Mocha)等等,这样会造成搭配方式有很多种,该如何来计算一杯咖啡的价格就成了问题,下面是最容易想到的办法。
//定义咖啡的抽象类 public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); } //加豆浆的HouseBlend public Class HouseBlendWithSoy extends Beverage { public HouseBlendWithSoy() { description = "HouseBlendWithSoy"; } public double cost() { return 1.99; } } //加摩卡的DarkRoast public Class DarkRoastWithMocha extends Beverage { public DarkRoastWithMocha() { description = "DarkRoastWithMocha"; } public double cost() { return 2.90; } } //..........
显然如果这样通过构造类来逐个算价格是很累人的,并且不利于扩展,假如某个原料价格改变,就要改变很多类,
下面用装饰者模式来解决这个问题:
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); } //定义调料的抽象类,让它继承Beverage public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } //这里很关键,让摩卡继承调料的抽象类,这样摩卡也是Beverage的子类,同时 //在摩卡类里面用一个实例变量记录Beverage public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha (Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Mocha"; } public double cost() { return 1.1 + beverage.cost(); } }
这里的继承作用在于让装饰者和被装饰者保持一样的类型,也就是有共同的超类,而不是利用继承获得“行为”,它的行为主要是通过装饰者与组件组合时会加入新的行为,是由组合对象而来。