定义
- 装饰者模式动态的将功能加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
几个要点
- 装饰者和被装饰者有相同的父类。
- 你可以用一个或多个装饰者装饰一个对象。
- 既然装饰者和被装饰者有相同的父类,所以在任何需要原始对象(被包装对象)的场合,可以用装饰过的对象代替它。
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者装饰对象
看看Java I/O中的InputStream怎么用的装饰者模式(io包中应用大量的装饰者模式,以InputStream为例)
InputStream
/**
* This abstract class is the superclass of all classes representing
* an input stream of bytes.
*
* <p> Applications that need to define a subclass of <code>InputStream</code>
* must always provide a method that returns the next byte of input.
public abstract class InputStream implements Closeable {
...
}
InputStream 是所有字节输入流的父类,继承InputStream的子类都要实现返回下一个输入字节的方法(read()).
FileInputStream
/**
* A <code>FileInputStream</code> obtains input bytes
* from a file in a file system. What files
* are available depends on the host environment.
*
* <p><code>FileInputStream</code> is meant for reading streams of raw bytes
* such as image data. For reading streams of characters, consider using
* <code>FileReader</code>.
public class FileInputStream extends InputStream {
...
}
FileInputStream主要功能是从文件中读入字节
BufferedInputStream
/**
* A <code>BufferedInputStream</code> adds
* functionality to another input stream-namely,
* the ability to buffer the input and to
* support the <code>mark</code> and <code>reset</code>
* methods. When the <code>BufferedInputStream</code>
* is created, an internal buffer array is
* created. As bytes from the stream are read
* or skipped, the internal buffer is refilled
* as necessary from the contained input stream,
* many bytes at a time. The <code>mark</code>
* operation remembers a point in the input
* stream and the <code>reset</code> operation
* causes all the bytes read since the most
* recent <code>mark</code> operation to be
* reread before new bytes are taken from
* the contained input stream.
*/
public
class BufferedInputStream extends FilterInputStream {
...
}
BufferedInputStream给InputStream增加一个功能:利用缓存高效读入字节,支持标记和重置。
- FileInputStream是InputStream的子类,继承之后针对文件读取添加功能,BufferedInputStream是FilterInputStream的子类,FilterInputStream继承了InputStream,所以BufferedInputStream同样是InputStream的子类,构造方法中需要传入一个InputStream。所以如何高效的读入文件就是这样了
public class IOTest {
public static void main(String[] args) {
File file = new File("test.txt");
try {
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
- 创建出来的FileInputStream作为被包装者传给BufferedInputStream,FileInputStream只负责读入文件,当想要提高效率的时候并没有在FileInputStream内部添加缓冲的方法,而是将起作为被装饰者传给BufferedInputStream,BufferedInputStream负责添加高效读入的功能,实现高效率读入文件.单一原则、开闭原则(对扩展开放,对修改关闭)体现的淋漓尽致!
结束语
仔细品味装饰者模式的要点,结合Java的IO操作就可以很好的理解装饰者模式了,最后附上一篇结合装饰者模式 优雅的为RecyclerView添加Header以及Footer的博文,加深理解。