上图的实现代码见:
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的总消费额。