深入浅出设计模式三——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.99Espresso Mocha $ 2.19Espresso Mocha Mocha $ 2.39Espresso Mocha Mocha Mocha $ 2.79
?
?
上例最后输出的就是客户点了Espresso咖啡,和两份Mocha调料和一份Whip的总消费额。
?