Head First Java 设计模式——装饰者模式

来源:互联网 发布:mac os山狮系统 编辑:程序博客网 时间:2024/06/02 07:29

        装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更具有弹性的替代方案。书中给出的是一个星巴兹的实例,他们准备更新订单系统,原先的类设计如下:

现在要实现,当客户购买咖啡时,可以要求加入各种调料,例如Milk、Soy、Mocha等,然后加入的调料会收取不同的费用。我们可能会按如下方法去尝试:

 

为每一种咖啡都建一个类,但是这样就会出现"类爆炸"的问题了。于是你可能想到要通过修改Beverage:

public abstract class Beverage {String description = "Unknown Beverage";boolean milk;boolean soy;boolean mocha;boolean whip;public boolean hasMilk();public void setMilk();public boolean hasSoy();public void setSoy();public boolean hasMocha();public void setMocha();public boolean hasWhip();public void setWhip();public String getDescription() {return description;}public double cost();}

这个时候cost()不是一个抽象方法,让它计算要加入的各种调料的价钱,然后子类仍将覆盖cost(),但是会调用超类的cost(),计算出基本饮料加上调料的价钱。但是这样又会出现几个问题:

1、一旦出现新的调料,我们就要加上新的方法,并改变超类的cost()方法。

2、以后可能会开发出新饮料,新的饮料某些调料可能不适合,但是这个设计方式,新的子类仍将要继承那些不适合的方法。

3、万一顾客想要双倍摩卡咖啡呢。

 

 

 

 

        下面采用新的方法:以饮料为主题,然后在运行时以调料来“装饰”饮料。用代码的方式呈现如下:

先从Beverage类下手:

public abstract class Beverage {String description = "Unknown Beverage";public String getDescription() {return description;}public abstract double cost();}

然后实现Condiment(调料)抽象类,也就是装饰者类:

public abstract class CondimentDecorator extends Beverage {public abstract String getDescription();}

接下来写饮料的代码,例如浓缩咖啡(Espresso),家常咖啡(HouseBlend):

public class Espresso extends Beverage {public Espresso() {description = "Espresso";}public double cost() {return 1.99;}}public class HouseBlend extends Beverage {public HouseBlend() {description = "House Blend Coffee";}public double cost() {return 0.89;}}

写调料代码,例如摩卡(Mocha):

public class Mocha extends CondimentDecorator {Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Mocha";}public double cost() {//这里计算带Mocha饮料的价钱,先把调用委托给被装饰对象,再加上Mocha的价钱,得到最终结果。return 0.20 + beverage.cost();}}

 最后,我们可以通过下面的方式来使用:

public class StarBuzzCoffee {public static void main(String args[]) {//订一杯Espresso,不需要调料。Beverage beverage = new Espresso();System.out.println(beverage.getDescription() + "$" + beverage.cost());//订一杯DarkRost咖啡。Beverage beverage2 = new DarkRost();//用Mocha装饰它。beverage2 = new Mocha(beverage2);//用第二个Mocha装饰它。beverage2 = new Mocha(beverage2);//用Whip装饰它。beverage2 = new Whip(beverage2);System.out.println(beverage2.getDescription() + "$" + beverage2.cost());//订一杯HouseBlend咖啡Beverage beverage3 = new HouseBlend();beverage3 = new Soy(beverage3);beverage3 = new Mocha(beverage3);beverage3 = new Whip(beverage3);System.out.println(beverage3.getDescription() + "$" + beverage3.cost());}}


 

这一章提到的设计原则:

1、开放-关闭原则(类应该对扩展开放,对修改关闭)。

原创粉丝点击