还记得被java io支配的恐惧吗,当读到core java 中的流与文件一章时,我整个人是懵逼的,为什么会设计这么多的类,怎么会记得清楚。直到我知道了Decorator设计模式,才知道了其中的用意所在,也才了解到了之前有人说java io设计的充满学院风的真意。
下面这张图是截取的core java volume II 中 Stream and Files一章中InputStream类图。
事实上,FilterInputStream是一个装饰器的基类,第三行中所有的类都继承自这一个类。而第二行中其他的类则是可以被装饰的具体的组件类。
当我们想要读取File中的数据时我们可以这么干:
FileInputStream fin = new FileInputStream("path");
DataInputStream din = new DataInputStream(fin);
double s = din.readDouble();
又或者我们想要构造一个既可以预读(PushBackInputStream
)又可以使用读取数据的缓存输入流,那么我们需要这样做:
DataInputStream din = new DataInputStream(
pin = new PushbackInputStream(
new BufferedInputStream(
new FileInputStream("path"))));
其中,FileInputStream
是被装饰的组件,而外层包装的BufferedInputStream
, PushbackInputStream
, DataInputStream
都是装饰器类。
对于OuputStream
以及Reader
和Writer
类型的设计都和这里相似。
这里的FilterOutputStream
即装饰器的基类。
看到这里,是不是手痒想写一个自己的装饰器类呢(并没有手痒,只有手累)。
现在我们实现一个将所有的输入都转换成小写的装饰器类:
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class LowerCaseInputStream extends FilterInputStream{
protected LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException{
int c = super.read();
return (c== -1 ? c : Character.toLowerCase(c));
}
public int read(byte[] b, int offset, int len) throws IOException{
int result = super.read(b, offset, len);
for(int i = offset; i< offset+result; i++){
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}