美文网首页
设计模式-装饰器模式

设计模式-装饰器模式

作者: ymjkMaster | 来源:发表于2017-09-25 16:45 被阅读0次

概述

装饰器模式一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。

一般来说,我们想给某个类或者对象添加行为有两种方式:继承方式,组合方式。装饰器模式使用的是组合方式。

实现

首先看下装饰器模式的UML图

DecoratorUML.png

可以看到,装饰器模式主要有

  • 抽象被装饰组件
  • 具体被装饰组件
  • 抽象装饰类
  • 具体装饰类

下面我将以煎饼的代码为例子,演示装饰器模式

/**
 * 抽象组件:煎饼
 */
public interface JianBing {
  JianBing make();
}

/**
 * 具体组件:杨氏煎饼
 */
public class YangShiJianBing implements JianBing {
  public JianBing make() {
    System.out.println("杨式煎饼");
    return this;
  }
}

/**
 * 抽象装饰器:调料
 */
public AbstractClass TiaoLiao implements JianBing{
  protected JianBing jianbing;

  public TiaoLiao(JianBing jianbing) {
    this.jianbing = jianbing;
  }

  public JianBing make() {
    jianbing.make();
  }
}


/**
 * 具体装饰器:加孜然
 */
public class AddZiRan extends TiaoLiao {
  public AddZiRan (JianBing jianbing) {
    super(jianbing);
  }

  public JianBing make() {
    jianbing.make();
    addZiRan(jianbing);
  }

  public void addZiRan(JianBing jianbing) {
    System.out.println(" 加孜然 ");
  }
}

/**
 * 具体装饰器:加辣
 */
public class AddPepper extends TiaoLiao {
  public AddPepper (JianBing jianbing) {
    super(jianbing);
  }

  public JianBing make() {
    jianbing.make();
    addPepper(jianbing);
  }

  public void addPepper(JianBing jianbing) {
    System.out.println(" 加辣 ");
  }
}

/**
 * 客户
 **/

public class Client {
  public static void main(String[] args) {
    // 煎饼 加孜然 加辣
    JianBing jianbing = new YangShiJianBing();
    JianBing jianBingAddPepper = new AddPepper(jianbing);
    JianBing jianBingAddZiRan = new AddZiRan(jianBingAddPepper);
    jianBingAddZiRan.make();
  }
}

可以看到,使用了装饰器模式之后,我们可以动态(甚至递归)地给组件(煎饼)添加需要的行为(调料),很棒。这和代理模式有本质的区别。

装饰器模式的实例

一个比较著名的例子是Java的I/O标准库的设计,其部分如下所示

JavaIOStreamUML.png

根据上图可以看出:

  • 抽象构建角色(Component):由InputStream扮演。这是一个抽象类,为各种子类型提供统一的接口。
  • 具体构件角色(ConcreteComponent):由ByteArrayInputStream、FileInputStream、StringBufferInputStream等类扮演。它们实现了抽象构件角色所规定的接口。
  • 抽象装饰角色(Decorator):由FilterInputStream、ObectInputStream等类扮演。它们实现了InputStream所规定的接口。
  • 具体装饰角色(ConcreteDecorator):由几个类扮演,分别是BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream。

装饰器模式的优点

装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

装饰器模式的缺点

这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

参考文章

相关文章

网友评论

      本文标题:设计模式-装饰器模式

      本文链接:https://www.haomeiwen.com/subject/cbjdextx.html