Java IO 中的设计模式
作者:终南 <li.zhongnan@hotmail.com >
设计模式是一个很理论的,也是一个很经验的东西。纯粹照着文档去理解设计模式不是一个好的方式,当经验有所增长的时候,回过头来看看设计模式这个比较玄的东西,还是比较有好处和用处的。
其实,在JDK中就使用了很多设计模式,为类库的可重用性、可扩展性和灵活性提供了强有力的支持。
JDK的I/O包中就主要使用到了两种设计模式:Adatper模式和Decorator模式
1。Adatper模式
Adatper模式又称为Wrapper模式。Wrapper模式这个词汇也许更能很好的理解其含义。比如JNI技术,具体的实现是C语言写的,不 过最后提供给用户的却是Java程序,也就是用Java包装/包裹/Wrapper了C代码。这就是Wrapper模式,也即Adapter模式。
通过使用Adatper模式,可以使得通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
InputStreamReader是Java IO中将byte流转换为char流的桥梁,其从从byte流中读取字节信息然后将其解码为char流,提供Reader接口所定义的方法。
从代码来看,InputStreamReader类中定义了一个 StreamDecoder 类的变量sd:
private final StreamDecoder sd;
当通过构造器 InputStreamReader(InputStream in) 创建一个InputStreamReader的实例时,通过传入的参数 InputStream 创建一个 StreamDecoder 实例 sd:
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
实现Reader接口的read()方法的代码为:
public int read() throws IOException {
return sd.read();
}
我们可以看到,实际上是调用StreamDecoder 的 read()方法来实现的。
形象地说,就是:
你和我合得来,和别人和不来,而我与别人合得来,你让我干活,我让别人干活。
除此之外,Java IO包下还有其他一些类使用了此种模式,如:
OutputStreamWriter:将char流转换成byte流。也就是使用Writer中的方法,但是结果将字符写入到byte流中。
StringReader/StringWriter:实现Reader/Writer到String的转换。
FileInputStream/FileOutputStream:连接File与InputStream/OutputStream,从而实现对文件的读写。
最后,看一下Adatper模式的图形说明:
2。Decorator模式
Decorator模式,顾名思义,就是修饰、装饰、锦上添花的意思。如果一个类已经有一些功能,你如果还想添加一些其他的功能,就可以使用Decorator模式。
通过使用Decorator模式,可以在运行时扩充一个类的功能。其原理是:增加一个装饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为 修饰类的构造器的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。装饰类必须和被装饰的类有相同的接口。
看看Java IO中的 LineNumberReader 类,该类继承自BufferedReader。可以将其看成实现了Reader接口,并且添加了readLine()、getLineNumber()、setLineNumber()这几项功能的类。
该类提供了两个构造器:
LineNumberReader(Reader in)
LineNumberReader(Reader in, int sz)
将原来的、被装饰的Reader作为构造器参数,除了实现Reader接口要求的功能外,还增加添加了新的功能。
在应用中,如果我们需要一行一行的从文件中读取字符,就可以利用LineNumberReader类来完成这样的这样的功能:
LineNumberReader reader = new LineNumberReader(new FileReader("file_name"));
在这里,Reader是一个公共接口,FileReader是一个被装饰的类,LineNumberReader 是装饰类。LineNumberReader 和 FileReader都实现了Reader接口,FileReader作为LineNumberReader 来构造一个LineNumberReader 实例。
对于Decorator模式,可以这样形同:
我们都给老板打工,我们配合做同样的事情,以我作为主,以你与老板联系为主,我做的差不多了,你帮我把把关,美化一下,最后由你想老板汇报。
Decorator模式可以用以下图形说明:
通过使用装饰模式,达到了减少类的数目的目的,而且也使得对性能的影响减至到最小。