场景:

购买咖啡时,可以要求加入各种调料,例如,豆浆,摩卡

豆浆,摩卡就是装饰者,咖啡是被装饰者。

 

不好的设计:

 

问题:

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

2、以后可能开发新的饮料,对这些饮料(冰茶),某些调料可能并不合适,但是在这个设计中,Tea子类

仍将继承那些不合法的方法,例如 奶泡。

3、万一顾客想要双倍摩卡,怎么办?

 

装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。
在这里,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”。

当我们将装饰者与组件组合时,就是在加入新的行为,所得到的新行为,并不是继承自
超类,而是由组合对象而来。

我们可以在任何时候,实现新的装饰者增加新的行为。如果依赖继承,每当需要新行为时,
还得修改现有的代码。

 

 

 

类图:

 

 

//超类(抽象组件)

public abstract class Beverage{

  String description = "Unknown Beverage";

   public String getDescription()

  {

    return description;

  }

  public abstract double cost();

}

 

//抽象装饰者(调料)

public abstract class CondimentDecorator extends Beverage{

  public abstract  String getDescription();

}

 

//饮料(具体组件)

public class Espresso extends Beverage{

   public Espresso ()

  {

    description = "Espresso";

  }

 

  public double cost()

  {

    return 1.99;

  }

}

 

//调料(具体装饰者)

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.99 + beverage.cost();

  }

}

摩卡(Mocha)是一个装饰者,所以让它扩展自CondimentDecorator 

CondimentDecorator 扩展自Beverage 

----------------------------------------------------------------------------

测试代码

public static void main(String[] args)

{

  Beverage  beverage  =  new Espresso();//一杯espresso

  beverage  = new  Mocha(beverage); //加入调料摩卡

  beverage  = new  Mocha(beverage); //再加入一份摩卡

  //加了两份摩卡的espresso的价格

  double price = beverage .cost();

}

要点:

在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码。

装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得复杂。

在选择需要被扩展的代码部分时要小心。每个地方都采用开发-关闭原则,是一种浪费,

也没必要,还会导致代码变得复杂且难以理解。

 

posted on 2018-01-25 12:08  邶风  阅读(126)  评论(0编辑  收藏  举报