在Java官方文档中,关于I/O流使用装饰器模式的部分主要介绍了如何使用装饰器模式实现不同的I/O功能。下面是一个简单的示例:
首先,我们有一个基本的输入流InputStream
,它定义了读取字节的操作:
public abstract class InputStream {
// 读取一个字节
public abstract int read() throws IOException;
// 读取多个字节到数组中
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
// 读取多个字节到数组的指定位置
public int read(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; i++) {
int c = read();
if (c == -1) {
return i;
}
b[off + i] = (byte) c;
}
return len;
}
// 关闭输入流
public void close() throws IOException {}
}
接下来,我们可以通过创建具体的装饰器类来扩展InputStream
的功能。
例如,BufferedInputStream
是一个装饰器类,用于提供缓冲功能,可以一次读取多个字节并存储在内部缓冲区中:
public class BufferedInputStream extends InputStream {
private InputStream inputStream;
private byte[] buffer;
private int position;
private int count;
public BufferedInputStream(InputStream inputStream) {
this.inputStream = inputStream;
this.buffer = new byte[8192];
this.position = 0;
this.count = 0;
}
@Override
public int read() throws IOException {
if (position >= count) {
fillBuffer();
if (count == -1) {
return -1;
}
}
return buffer[position++];
}
private void fillBuffer() throws IOException {
count = inputStream.read(buffer);
position = 0;
}
}
类似地,DataInputStream
是另一个装饰器类,用于提供读取基本数据类型的功能:
public class DataInputStream extends InputStream {
private InputStream inputStream;
public DataInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() throws IOException {
return inputStream.read();
}
// 读取int类型数据
public int readInt() throws IOException {
byte[] buffer = new byte[4];
inputStream.read(buffer);
return ByteBuffer.wrap(buffer).getInt();
}
// 读取double类型数据
public double readDouble() throws IOException {
byte[] buffer = new byte[8];
inputStream.read(buffer);
return ByteBuffer.wrap(buffer).getDouble();
}
}
通过使用不同的装饰器类,我们可以根据需要组合它们来实现不同的I/O功能。例如,我们可以将BufferedInputStream
和DataInputStream
装饰器结合起来,以在读取字节流时提供缓冲和处理基本数据类型的能力:
InputStream inputStream = new FileInputStream("data.txt");
inputStream = new BufferedInputStream(inputStream);
inputStream = new DataInputStream(inputStream);
通过这种方式,我们可以动态地为输入流添加所需的功能,并将其组合在一起以实现多样化的I/O操作。