跳至主要內容

Java I/O - 装饰者模式

Zenghr大约 2 分钟Java

Java I/O 中的设计模式(装饰)

提示

本文了解 Java 设计模式中的一种模式,装饰者模式,在 Java.ioopen in new window 包中的 包装流 中就使用了装饰者模式

如需了解装饰器模式详解请看👉 装饰器模式详解

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构,装饰器模式中有四个重要的角色

  • 抽象构件角色 (Component)
  • 具体构件角色(ConcreteComponent)
  • 抽象装饰者角色(Decorator)
  • 具体装饰者角色(ConcreteDecorator)

InputStream 举例,它就是一个 抽象的构建角色(Component)

public abstract class InputStream implements Closeable {
    // ...
}

且定义有抽象方法

public abstract int read() throws IOException;
public void close() throws IOException {}

该抽象方法由具体的子类去实现,直接继承了 InputStream,并且提供某一特定功能的子类有

  • ByteArrayInputStream
  • FileInputStream
  • FilterInputStream
  • PipedInputStream
  • DataInputStream

这些子类都有自己特定的功能,FileInputStream 代表文件输入流,我们称这些子类为 具体构件角色(ConcreteComponent)

抽象装饰者(Decorator)

在这些类中有一个类和其他类不同 - FilterInputStream,查看其源代码可知,其内部维护了一个 InputStream 对象,并且它的所有方法,都是调用这个成员对象的同名方法,那么这个 FilterInputStream 就是一个抽象装饰者(Decorator)

public class FilterInputStream extends InputStream {
    protected volatile InputStream in;
    
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
    
    public int read() throws IOException {
        return in.read();
    }
    
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
    
    public int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }
    
    public long skip(long n) throws IOException {
        return in.skip(n);
    }
    
    public int available() throws IOException {
        return in.available();
    }
    
    public void close() throws IOException {
        in.close();
    }
    
    public synchronized void mark(int readlimit) {
        in.mark(readlimit);
    }

    public synchronized void reset() throws IOException {
        in.reset();
    }
    
    public boolean markSupported() {
        return in.markSupported();
    }
}

FilterInputStream 类下面有它的一些子类,我们主要看常用的 BufferedInputStream 缓冲包装流,查看它的源代码

public class BufferedInputStream extends FilterInputStream {
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }
    
    public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }
}

查看它的 read() 方法源码可知,BufferedInputStream 就是一个具体的装饰者角色(ConcreteDecorator),它能为一个原本没有缓冲功能的 InputStream 添加上缓冲的功能,例如 FIleInputStream 并没有缓存功能,使用 BufferedInputStream 来装饰它,使得其具备缓存能力,提高程序的性能