1. 模式意图
动态地给一个对象添加一些额外的职责;Decorator模式相比生成子类更为灵活;(别名Wrapper)
有时候,我们需要为一个对象而不是整个类添加一些新的功能,如果使用继承机制来实现,不同的功能组合将会导致类的爆炸.
2. 模式定义
Component: 定义一个对象接口,可以给这些对象动态地添加职责;
ConcreteComponent: 定义一个对象,可以给这个对象添加一些职责;
Decrator: 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
ConcreteDecratorA/B: 想组件添加职责;
Decrator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作;
3. 模式实现
4. 模式应用
4.1 Java IO
在由InputStream, OutStream, Reader 和 Writter代表的等级结构内部,有一些流处理器可以对另一些流处理器起到装饰作用,形成新的,具有改善了的功能的流处理器。装饰者模式是Java I/O库的整体设计模式:
- java.io.InputStream (implements java.io.Closeable)
- java.io.ByteArrayInputStream
- java.io.FileInputStream
- java.io.FilterInputStream
- java.io.BufferedInputStream
- java.io.DataInputStream (implements java.io.DataInput)
- java.io.LineNumberInputStream
- java.io.PushbackInputStream
- java.io.ObjectInputStream (implements java.io.ObjectInput, java.io.ObjectStreamConstants)
- java.io.PipedInputStream
- java.io.SequenceInputStream
- java.io.StringBufferInputStream
- java.io.OutputStream (implements java.io.Closeable, java.io.Flushable)
- java.io.ByteArrayOutputStream
- java.io.FileOutputStream
- java.io.FilterOutputStream
- java.io.BufferedOutputStream
- java.io.DataOutputStream (implements java.io.DataOutput)
- java.io.PrintStream (implements java.lang.Appendable, java.io.Closeable)
- java.io.ObjectOutputStream (implements java.io.ObjectOutput, java.io.ObjectStreamConstants)
- java.io.PipedOutputStream
- java.io.Reader (implements java.io.Closeable, java.lang.Readable)
- java.io.BufferedReader
- java.io.LineNumberReader
- java.io.CharArrayReader
- java.io.FilterReader
- java.io.PushbackReader
- java.io.InputStreamReader
- java.io.FileReader
- java.io.PipedReader
- java.io.StringReader
- java.io.BufferedReader
- java.io.Writer (implements java.lang.Appendable, java.io.Closeable, java.io.Flushable)
- java.io.BufferedWriter
- java.io.CharArrayWriter
- java.io.FilterWriter
- java.io.OutputStreamWriter
- java.io.FileWriter
- java.io.PipedWriter
- java.io.PrintWriter
- java.io.StringWriter
try
{InputStream in = new DataInputStream(new FileInputStream("test.txt"));
}catch (FileNotFoundException e)
{e.printStackTrace();
}
这是一个典型的Decorator模式的使用, FileOutputStream相当于Component,DataOutputStream就是一个Decorator。
模式图如下:
根据输入流的源的类型,可以将这些流类分成两种,即
原始流类(Original Stream)和
连接流处理器(Wrapper Stream):
原始流处理器:
原始流处理器接受一个Byte数组对象,String对象,FileDiscriptor对象或者不同类型的流源对象,以InputStream为例,原始流处理器包括以下四种:
ByteArrayIInputStream:为多线程的通信提供缓冲区操作功能,接受一个Byte数组作为流的源;
FileInputStream:建立一个与文件有关的输入流,接受一个File对象作为流的源;
PipedInputStream:可以与PipedOutputStream配合使用,用于读入一个数据管道的数据,接受一个PipedOutputStream作为源;
StringBufferInputStream:将一个字符串缓冲区转换为一个输入流,接受一个String对象作为流的源;
链接流处理器:
所谓链接流处理器,就是可以接受另一个流对象作为源,并对之进行功能扩展的类。InputStream类型的链接处理器包括以下几种,它们都接受另一个InputStream对象作为流源:
FilterInputStream:过滤输入流,它将另一个输入流作为流源,子类包括:
BufferedInputStream:用来从硬盘将数据读入到一个内存缓冲区,并从缓冲区提供数据;
DataInputStream:提供基于多字节的读取方法,可以读取原始类型的数据;
LineNumberInputStream:提供带有行计数功能的过滤输入流;
PushbackInputStream:提供特殊的功能,可以将已经读取的字节推回输入流中;
ObjectInputStream:可以将使用ObjectInputStream串行化的原始数据类型和对象重新并行化;
SequeneInputStream:可以将两个已有的输入流链接起来,形成一个输入流,从而将多个输入流排列构成一个输入流序列;
按照上面的这种原始流处理器和链接流处理器的划分,可以用下面的结构图来描述它们之间的关系:
上面的流处理器图跟装饰者模式的结构图有着显而易见的相同之处。
链接流对象接受一个原始流对象或者另外一个链接流对象作为流源,它们对流源的内部工作方法做了相应的改变,这种改变是装饰者所要达到的目的。 例如:
BufferedInputStream装饰了InputSteam的内部工作方式,使得流的读入操作使用了缓冲机制。在使用了缓冲机制后,不会对每一次的流读入操作都产生一个物理的读盘操作,从而提高了程序的效率,在涉及到物理流的读入时,都应当使用这个装饰流类。