装饰器模式

来源:互联网 发布:数据分析的基本流程 编辑:程序博客网 时间:2024/06/16 05:56

一、意图与动机

动态的给一个对象而不是整个类添加一些额外的职责。

二、适用性

  1. 一下情况适合使用装饰器模式
  2. 不影响其它对象职责的情况下,动态、透明的各条单个对象添加职责
  3. 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持没有组组则将产生大量的子类,使得子类数目呈爆炸式增长。另一种情况是因为类定义被隐藏,或者类定义不能用于生成子类。

三、结构


四、实现


  1. 使用装饰器模式需要注意以下几点
  2. 接口一致性。装饰对象的接口必须与它装饰的对象的接口是一致的,因此,结构图中,CoreFunctionality和OptionalWrapper必须有一个公共的接口。
  3. 省略抽象的Decorator类,也就是结构图中的OptionalWrapper类。当仅仅需要添加一个职责时,没有必要定义抽象的Decorator类,直接在将请求转发的职责放到具体类中
  4. 保持基础接口的简单性。为了保持接口一致性,原始类和装饰类有一个公共的接口,保持这个公共接口的简单性很重要,否则CoreFunctionality会过于庞大和复杂。
  5. 改变对象外壳与改变对象内核。可以将Decorator看着一个对象的外壳,可以改变对象的行为而不是类。如果要改变对象的内核,策略模式是一种选择

五、案例

装饰器模式在java的IO库中大量使用,现抽取部分示例如下

public class BufferedReader extends Reader {    private Reader in;    private char cb[];    private int nChars, nextChar;    private static final int INVALIDATED = -2;    private static final int UNMARKED = -1;    private int markedChar = UNMARKED;    private int readAheadLimit = 0; /* Valid only when markedChar > 0 */    /** If the next character is a line feed, skip it */    private boolean skipLF = false;    /** The skipLF flag when the mark was set */    private boolean markedSkipLF = false;        // ......}

public class InputStreamReader extends Reader {    private final StreamDecoder sd;    /**     * Creates an InputStreamReader that uses the default charset.     *     * @param  in   An InputStream     */    public InputStreamReader(InputStream in) {        super(in);        try {            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object        } catch (UnsupportedEncodingException e) {            // The default encoding should always be available            throw new Error(e);        }    }    // ......}

类似该例子,java io库中,还有很多使用装饰器模式的例子,如FilterReader、FilterWriter、BufferedWriter、PrintWriter、LineNumberReader、PushBackReader。

0 0
原创粉丝点击