天天看点

装饰者模式 Decorator Pattern一、是什么二、问答三、实例

父博文地址:设计模式 - Design Patterns

一、是什么

  1. 问题

    使用继承是静态的扩展:

    • 随着系统功能增多造成了类数量指数级增加。
    • 且基类的功能并不适用于所有子类。
  2. 寻找一个设计模式原则

    开闭原则:类应该对扩展开放,对修改关闭。换句话说:在不修改类的前提下扩展类。

  3. 装饰者模式定义

    动态的将责任附加到对象 上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    类图如下:

    装饰者模式 Decorator Pattern一、是什么二、问答三、实例

二、问答

  1. AbstractDecorator

    及其子类依然继承自

    AbstractComponent

    不是吗?

    我们依然使用了继承,的确如此。不过这么做的重点在于,装饰者和被装饰者需要是同一个类型,这很关键。我们只是利用继承达到“类型匹配”,而不是利用继承获取“行为”。

  2. 加入行为

    我们不是通过继承来“加入新行为”,而是通过“组合”。

  3. 为什么装饰者是抽象类?

    通常使用抽象类,当然Java 中也可以使用接口,此时需要把构造函数定义在各个装饰者子类中。

三、实例

1.

FilterInputStream

InputStream

的装饰器

类图如下:

装饰者模式 Decorator Pattern一、是什么二、问答三、实例
  1. 介绍

    InputStream

    是抽象被装饰类,

    ObjectInputStream

    ,

    FileInputStream

    ,

    ByteArrayInputStream

    等是可以被装饰的具体组件。

    FilterInputStream

    是装饰者类(这里没有设计为抽象),

    BufferedInputStream

    ,

    LineNumberInputSream

    ,

    DataInputSream

    等是具体的装饰者类。
  2. FilterInputStream

    代码
    public class FilterInputStream extends InputStream {
    
        protected volatile InputStream in;
    
        protected FilterInputStream(InputStream in) {
            this.in = in;
        }
    
        public int read() throws IOException {
            return in.read();
        }
    
        // others
    }
               
    可以看到,包装类只有一个有参数的构造函数,参数是被包装类。包装类可以动态的添加功能,这里覆盖了

    read()

    并简单的调用被包装类的同名方法。
  3. 一个可能的用例
    装饰者模式 Decorator Pattern一、是什么二、问答三、实例

    FileInputSream

    BufferedInputSream

    装饰,

    BufferedInputSream

    又被

    LineNumberInputSream

    装饰。

继续阅读