深入显出设计模式三——Beverage实现(装饰者模式)
深入浅出设计模式三——Beverage实现(装饰者模式)
上图的实现代码见:
http://quicker.iteye.com/blog/554032
定义:
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案。
设计原则五:代码应该对扩展开放,对修改关闭。
Beverage系统是一个销售咖啡的订单系统,主要销售咖啡,咖啡有多种,另外有多个种类的调料。
那么如果将Beverage设为超类,其它的咖啡调料等都从这个类继承,并且每个类都有一个cost的计费方法。
类图如下:
上面的类看起来要爆炸了。。。
我们看看使用装饰模式后的类图。
http://quicker.iteye.com/blog/554032
文中讲过一点:
在装饰者类中使用了继承,又把父类的引用作为它的属性。
这是因为继承能使类型保持一致,而我们要灵活的使用类的行为则需要使用组合。
继承:装饰者要与被装饰者保持一样的类型,因为装饰者必须能取代被装饰者。
组合:当我们将装饰者与组件组合时,就是加入新的行为。所得到的新的行为,不是继承自超类,而是由组合对象得来的。
所以在上图中继承Beverage抽象类,是为了有正确的类型,而不是继承它的行为。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系。
在上例中正是因为使用对象组合,我们才可以把所有饮料和调料更有弹性地加以混和与匹配,比如客户同时点了多种咖啡和调料的时候。
代码如下:
package com.lwf.disign.learn.decorator; public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); }
package com.lwf.disign.learn.decorator; public class Espresso extends Beverage { public Espresso(){ description = "Espresso"; } public double cost() { return 1.99; } }
package com.lwf.disign.learn.decorator; public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
package com.lwf.disign.learn.decorator; 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 0.200 + beverage.cost(); } }
package com.lwf.disign.learn.decorator; public class Whip extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + " Mocha"; } public double cost() { return 0.400 + beverage.cost(); } }
测试类:
package com.lwf.disign.learn.decorator; public class BeverageTest { public static void main(String[] args) { Beverage b = new Espresso(); System.out.println(b.getDescription() + " $ " + b.cost()); b = new Mocha(b); System.out.println(b.getDescription() + " $ " + b.cost()); b = new Mocha(b); System.out.println(b.getDescription() + " $ " + b.cost()); b = new Whip(b); System.out.println(b.getDescription() + " $ " + b.cost()); } }
输出结果为:
Espresso $ 1.99 Espresso Mocha $ 2.19 Espresso Mocha Mocha $ 2.39 Espresso Mocha Mocha Mocha $ 2.79
上例最后输出的就是客户点了Espresso咖啡,和两份Mocha调料和一份Whip的总消费额。