A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本文将介绍一对特殊的字节流:FilterInputStream与FilterOutputStream,以及它们与装饰模式之间的联系。

FilterInputStream、FilterOutputStream是过滤器字节输入输出流。它们的主要用途在于封装其他的输入输出流,为它们提供一些额外的功能。

FilterInputStream

下面我们以FilterInputStream为例来学习下FilterInputStream与装饰模式的关系。

FilterInputStream.java

package java.io;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();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

从FilterInputStream的源码中可以看到,它本身只是简单地重写那些将所有请求传递给所包含输入流的InputStream所有方法。也就是说FilterInputStream并没有提供什么装饰功能。FilterInputStream的子类可进一步重写这些方法中的一些方法,来提供装饰功能。它的常用的子类有BufferedInputStream和DataInputStream。比如,BufferedInputStream的作用就是为它装饰的输入流提供缓冲功能。

装饰功能是如何实现的呢?

从FilterInputStream的构造方法中可以看到,

protected FilterInputStream(InputStream in) {    this.in = in;}
  • 1
  • 2
  • 3

当我们在创建FilterInputStream实例时需要传入一个InputStream子类的实例。比如:当构造FilterInputStream实例fis时传递进去的是ByteArrayInputStream的实例bais,这样调用fis.read()是实际上调用的是bais.read()。

public int read() throws IOException {    return in.read();}
  • 1
  • 2
  • 3

当然,FilterInputStream并没有提供装饰功能,但如果提供了装饰功能是什么样子呢?我们把FilterInputStream的read方法改下。

public int read() throws IOException {    decoratorFunc();    return in.read();}public void decoratorFunc(){    //这里是装饰方法的内容}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样执行fis.read就相当于执行了fis.decoratorFunc()和bais.read()两个方法。decoratorFunc()就是FilterInputStream为其他输入流提供的装饰功能。

想了解更多关于装饰模式的内容请参考设计模式(9)-装饰模式

几个类在装饰模式中对应的角色如下所示。

  • InputStream-抽象构件。
  • ByteArrayInputStream-具体构件。
  • FilterInputStream-具体装饰类。

FilterOutputStream和FilterInputStream类似,本文不再做讲述。

总结
  • FilterInputStream、FilterOutputStream是过滤器字节输入输出流。它们的主要用途在于封装其他的输入输出流,为它们提供一些额外的功能。
  • FilterInputStream、FilterOutputStream并没有提供什么装饰功能。FilterInputStream、FilterOutputStream的子类可进一步重写这些方法中的一些方法,来提供装饰功能。
  • FilterInputStream装饰功能的实现的关键在于类中有一个InputStream字段,依赖这个字段它才可以对InputStream的子类提供装饰功能。FilterOutputStream也是如此。

对FilterInputStream与FilterOutputStream的介绍就到这里。想了解Java8 I/O源码的更多内容,请参考

版权声明


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马