设计模式—从装饰器模式的角度来分析 Java IO

2019-05-21  本文已影响0人  未见哥哥

下面来看看一个具体的实例

通过下面几行代码就将 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 角度来看装饰者设计模式

image.png
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 具体的装饰器对象,具体的工作是将数据写入到缓冲区中。

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号

上一篇 下一篇

猜你喜欢

热点阅读