装饰者模式 Decorator Pattern

Posted 有且仅有

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式 Decorator Pattern相关的知识,希望对你有一定的参考价值。

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


一、是什么

  1. 问题

    使用继承是静态的扩展:

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

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

  3. 装饰者模式定义

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

    类图如下:

二、问答

  1. AbstractDecorator 及其子类依然继承自AbstractComponent 不是吗?

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

  2. 加入行为

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

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

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

三、实例

1. FilterInputStreamInputStream 的装饰器

类图如下:

  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. 一个可能的用例

    FileInputSreamBufferedInputSream装饰,BufferedInputSream又被LineNumberInputSream装饰。

以上是关于装饰者模式 Decorator Pattern的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之——装饰者模式(Decorator pattern)

装饰者模式 Decorator Pattern

装饰者模式 Decorator Pattern

设计模式 —— 装饰器模式(Decorator Pattern)

Head First设计模式之装饰者模式(Decorator Pattern)

大厂设计模式面试必备装饰者模式(Decorator Pattern)!