概述
- 节点流 <-> 过滤流
- 输入流 <-> 输出流
- 字节流 <-> 字符流
装饰模式
构成
- 抽象构件(Component)
- InputStream;OutputStream;Reader;Writer
- 具体构件(ConcreteComponent)
- ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream
- ByteArrayOutputStream、FileOutputStream、PipedOutputStream、ObjectOutputStream
- FilterReader、InputStreamReader、CharArrayReader、PipedReader、StringReader
- BufferedWriter、CharArrayWriter、FilterWriter、OutputStreamWriter、PipedWriter、PrintWriter、StringWriter
- 抽象装饰(Decorator)
- FilterInputStream;FilterOutputStream;FilterReader,BufferedReader,InputStreamReader;OutputStreamWriter
- 具体装饰(ConcreteDecorator)
- BufferedInputStream、DataInputStream、LineNumberInputStream、PushbackInputStream
- BufferedOutputStream、DataOutputStream、CheckedOutputStream、CipheOutputSteam
- LineNumberReader、PushbackReader、FileReader
- FileWriter
关系
InputStream:被装饰者
FileInputStream:具体被装饰者
FilterInputStream:装饰者
DataInputStream:具体装饰者
abstract class InputStream
FileInputStream extends InputStream
FilterInputStream extends InputStream
DataInputStream extends FilterInputStream implements DataInput
InputStream,节点输入字节流的祖宗,抽象类
read():留给子类实现
public abstract int read() throws IOException;
read(byte b[]):0偏移,塞满数组b
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
read(byte b[], int off, int len):可以看到,其实就是一个字节一个字节地读取,塞入字节数组b
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
FileInputStream,节点流,继承自InputStream
read():native搞起
public int read() throws IOException {
return read0();
}
private native int read0() throws IOException;
read(byte b[]):还是native
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
private native int readBytes(byte b[], int off, int len) throws IOException;
read(byte b[], int off, int len):native
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
private native int readBytes(byte b[], int off, int len) throws IOException;
DataInputStream,过滤流,继承FilterInputStream实现DataInput
read(byte b[]):
这个in是个InputStream的引用,这就是装饰模式;
那么,这个in是什么时候进来的呢,是在DataInputStream的构造方法里进来的
public final int read(byte b[]) throws IOException {
return in.read(b, 0, b.length);
}
read(byte b[], int off, int len):
public final int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
readInt():
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
半透明装饰
首先,说一说透明装饰,或者说理想的装饰模式,那当然是具体装饰者的方法集合,不要超出被装饰者的;这样的话,当我们在业务方法中调用装饰者(往往是接口或者抽象类的一个引用)方法时,就不用担心转型问题;说道这里可能还是很迷糊,那么说个例子,PushbackInputStream。
PushbackInputStream extends FilterInputStream
先看下常规使用装饰模式:
public Client{
private InputStream in;
public Client(InputStream in){
this.in = in;
}
......
public void read(byte[] b){
in.read(b, 0, b.length);
}
}
Socket socket = ...;
byte[] b = ...;
Client client = new Client(socket.getInputStream());
client.read(b);
那么上面这个是ok的,不会有什么问题。
然后,这个时候由于我知道PushbackInputStream这个类,完了我还想用它提供的unread方法。
public Client2{
private InputStream in;
public Client2(InputStream in){
this.in = in;
}
......
public void unread(int b){
in.unread(b);
}
}
Socket socket = ...;
int b = ...;
Client2 client2 = new Client2(new PushbackInputStream(socket.getInputStream()));
client2.unread(b);
那么,这个时候就有问题了,因为unread这个方法是PushbackInputStream(可以认为是个具体装饰者)特有的,InputStream里压根没有。那么Client2的这个unread方法是有问题的,他需要改成这样:
public void unread(int b){
((PushbackInputStream)in).unread(b);
}
那么,说到这个半透明装饰,倒不能说是PushbackInputStream不好,毕竟人家提供额外的unread方法,只是我们自己使用的时候需要注意到这个点。
其他典型代码片段
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 {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
FileInputStream
FileInputStream extends InputStream
public int read() throws IOException {
return read0();
}
// native
private native int read0() throws IOException;
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
/ native
private native int readBytes(byte b[], int off, int len) throws IOException;
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
DataInputStream
DataInputStream extends FilterInputStream implements DataInput
FilterInputStream extends InputStream
// 装饰模式-过滤流的体现,in就是一个InputStream
public final int read(byte b[]) throws IOException {
return in.read(b, 0, b.length);
}
public final int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
InputStreamReader
- StreamDecoder