下面来看看一个具体的实例
通过下面几行代码就将 Hello IO 这段字符串写入到文件 io.txt 中,那其中是如何运用到装饰者设计模式的?
File file = new File("./io.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
dataOutputStream.writeUTF("Hello IO");
通过 FileOutputStream 就可以将对字符串写入到文件中
fileOutputStream.write("Hello IO".getBytes());
而这种方式会每次调用 write(int) 都会去操作磁盘,为了减少频繁的操作磁盘,这里引入了 BufferedOutputStream ,它内部在 write 数据会首先将其写入到到缓冲区中,当调用 flush 时才一次将其写入到磁盘中。
但是为我们想写入的是 Java 数据类型的数据,例如 String,int,long 等,因此我们在这里又引入了 DataOutStream 来实现这个功能,它内部实现了很多 writeXxx() 方法。
之所以能够这么方便地玩转这一系列的操作,都是因为 Java IO 内部使用到了装饰者设计模式
从 IO 角度来看装饰者设计模式

- 抽象主题
public abstract class OutputStream implements Closeable, Flushable {}
- 装饰器类
装饰器类 FilterOutputStream 持有被装饰对象 out 引用
public
class FilterOutputStream extends OutputStream {
protected OutputStream out;
public FilterOutputStream(OutputStream out) {
this.out = out;
}
public void write(int b) throws IOException {
out.write(b);
}
}
- 具体的装饰器对象 BufferedOutputStream/DataOutputStream
BufferedOutputStream 具体的装饰器对象,具体的工作是将数据写入到缓冲区中。
public class BufferedOutputStream extends FilterOutputStream {
public BufferedOutputStream(OutputStream out) {
this(out, 8192);
}
public synchronized void write(int b) throws IOException {
//具体装饰器类对象实现具体的业务逻辑
if (count >= buf.length) {
flushBuffer();
}
buf[count++] = (byte)b;
}
public synchronized void flush() throws IOException {
flushBuffer();
//具体装饰器类对象调用被装饰对象的方法
out.flush();
}
}
DataOutputStream 负责写入 Java 数据类型的包装类,内部会将数据转化为out.write(int) 去调用被装饰对象 out 的 write(int) 方法。
public class DataOutputStream extends FilterOutputStream implements DataOutput {
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
}
- 具体的抽象主题对象
FileOutputStream 是具体的抽象主题,主要是将数据写入的操作将数据写入到文件中。
public class FileOutputStream extends OutputStream{
public void write(byte b[], int off, int len) throws IOException {
// Android-added: close() check before I/O.
if (closed && len > 0) {
throw new IOException("Stream Closed");
}
// Android-added: Tracking of unbuffered I/O.
tracker.trackIo(len);
// Android-changed: Use IoBridge instead of calling native method.
IoBridge.write(fd, b, off, len);
}
}
本文是笔者学习之后的总结,方便日后查看学习,有任何不对的地方请指正。
记录于 2019年5月21号
网友评论