装饰者模式

定义

    动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。

理解

    使用对象组合的方式,做到运行时装饰类。这样可以在不修改任何底层代码的情况下,给你的(或别人的)对象赋予新的职责。动态的将责任附加到对象上,想要扩展功能,装饰者提供有别于继承的另一种选择。我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。这样的设计具有弹性,可以应对改变,可以接收新的功能来应对改变。

设计初衷

    通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。
装饰者类类在构造中引入一个被装饰组件,拿到它之后可以在组件的行为(方法)的前后加上自己的行为,甚至可以将组件的行为覆盖掉,达到动态扩展新行为的功能。

UML类图

应用实例

这里引用了《Head First 设计模式》中关于装饰者模式的例子

    一份咖啡可能加摩卡、奶泡等辅料。而每一个辅料的价格不一样,如何设计程序才能让最终计算咖啡价格更简单。使用装饰者模式再好不过。

/**
 * 该类为饮料抽象类,定义抽象方法cost(),用于计算饮料价格
 * 抽象组件
 * @author xiangge.zeng
 */
public abstract class Beverage {
      String description = "UnKnown Beverage";
      public String getDescription(){
              return description;
      }
      public abstract double cost();
}
 
/**
 * 浓缩咖啡,是一种饮料,继承Beverage基类
 * 具体组件
 * @author xiangge.zeng
 *
 */
public class Espresso extends Beverage{
      /**
       * 为了设置该饮料的描述,编写该构造器
       * description实例变量继承于父类
       */
      public Espresso(){
              description  = "Espresso";
      }
      /**
       * 计算价钱方法,返回浓缩咖啡的价格
       */
      public double cost() {
              return 1.99;
      }
}
/**
 * 调料类,继承于饮料基类。是抽象装饰者,用于装饰饮料组件
 * @author xiangge.zeng
 *
 */
public abstract class CondimentDecorator extends Beverage{
      public abstract String getDescription();
}
 
/**
 * 装饰者摩卡,用于装饰咖啡.装饰者扩展于组件,为了和组件保持统一从而装饰组件
 * @author xiangge.zeng
 *
 */
public class Mocha extends CondimentDecorator{
 
      /**
     * 让装饰者在构造中引入一个组件,从而拿到它、装饰它
       * 做法如下: 1、加入组件实例变量
       *              2、组件作为构造参数传入构造器
       */
      private Beverage beverage;
      public Mocha(Beverage beverage) {
              this.beverage = beverage;
      }
      public String getDescription() {
              /**
               * 装饰过后的描述:组件+装饰描述
               */
              return beverage.getDescription()+"Mocha";
      }
 
      public double cost() {
              /**
               * 装饰过的价格也是:组件价格+装饰价格
               * 要计算带摩卡饮料的价钱,首先把调用委托给被装饰对象
               */
              return .20+beverage.cost();
      }
 
}
 
public class CoffeShop {
      public static void main(String[] args) throws Exception{
              //点一杯浓缩咖啡
              Beverage b = new Espresso();
              //打印价格与描述
              System.out.println(b.getDescription()+" :"+b.cost());
              //点一杯加两分摩卡和一份WHip的Espresso
              Beverage b1 = new Espresso ();
              //b1被两份Mocha和一份Whip所装饰
              b1 = new Mocha(b1);
              b1 = new Mocha(b1);
              b1 = new Whip(b1);
              //或可以直接写成如下形式:
              b1 = new Mocha(new Mocha(new Whip(b1)));             
              //打印价格与描述
              System.out.println(b1.getDescription()+" :"+b1.cost());
      }
}

调用过程


Java中的装饰者模式:Java IO

FileInputStream是低级流,它从文件中读取数据,但是它的性能有时不尽如人意。我们可以用一些高级流装饰它。所谓的套用;它是“被装饰者”。BufferedInputStream是一个具体的装饰者,它在原来的基础上实现了利用缓冲来改进性能。
BufferedInputStream,LineNumberInputStream都扩展自FilterInputStream,它是一个抽象的装饰类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值