作者:Flyingis
任何程序语言的I/O设计都是一项具有挑战的任务,因为数据的传输存在多种可能,这些可能不仅存在于数据发送端和接收端(文件、网络链接等),还存在于这些数据的多种存在方式,例如缓冲区数据、顺序存取数据、字符数据、字节数据等等。
Java的I/O使用“流”这个抽象的概念,它屏蔽了实际的I/O设备中处理数据的细节。在实际的应用中,我们很少使用单一的类来创建流对象,而是通过多个对象来提供所需要的I/O功能。Java从1.0到1.1到1.4多I/O类库作了多次重大修改,具体的可以参考相关的书籍或Sun官方网站。这里是从模式的角度来分析Java的I/O类库的设计。
Strategy设计模式
将会发生变化的代码封装在单独的类(Strategy对象)中,供其他保持不变的类使用,实现某种算法或应用,这是Strategy设计模式的一般思想。在Java I/O中,一个典型的应用是File类,它可以代表一个特定文件的名称,也可以代表一个目录下一组文件的名称。当我们要查询显示一个目录下特定文件类型的所有文件对象信息时,就需要将这个目录下的文件过滤,找到所需要的对象。
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class AlphabeticComparator implements Comparator {
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
return s1.toLowerCase().compareTo(s2.toLowerCase()); //比较时不考虑大小写
}
}
public class FruitList {
public static FilenameFilter filter(final String regex) {
return new FilenameFilter() {
private Pattern pattern = Pattern.compile(regex);
public boolean accept(File dir, String name) {
return pattern.matcher(new File(name).getName()).matches();
}
};
}
public static void main(String[] args) {
File path = new File(“.”);
String[] list;
if (args.length == 0)
list = path.list(); //搜索出该目录下所有类型的文件
else
list = path.list(filter(args[0])); //搜索出该目录下指定类型的文件
Arrays.sort(list, new AlphabeticComparator());
for (int i = 0; i < list.length; i++)
System.out.println(list[i]);
}
}
在上述代码中,有两个地方使用了Strategy设计模式,一个是AlphabeticComparator类,用来在忽略字符串大小写的情况下提供排序的规则,另一个就是FilenameFilter接口,使用了匿名内部类的设计,然后将其中实现的accept()规则提供给File类的list方法使用。这里是用来判断正则表达式regex是否和文件名匹配,当运行程序在命令操作符中输入“E.*\.java”时,搜索到的是该目录下所有.java文件。
File类除了上述用法外,还可以创建或删除目录,查看文件的信息,包括文件大小、最后修改日期,读写状态等,具体的可以参考JDK文档。
Decorator设计模式
在http://www.j2eesp.com上有对Decorator设计模式的定义:动态给一个对象添加一些额外的职责,就像在墙上刷油漆。使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。Decorator模式规定所有封装于初始对象内部的对象具有相同的接口,这使得该模式的应用具有透明性。
在Java I/O设计中,Decorator模式主要体现在filter类的设计上,抽象类filter是所有Decorator模式类的基类。但是Decorator模式同样存在缺点:在编写程序时,它在给开发人员提供了灵活性的同时,增加了代码的复杂性,造成了Java I/O类操作不便,因为很多I/O设计中都需要应用Decorator模式,增加一些类来完成该设计。
例如在Java 1.0中,FilterInputStream从InputStream中读取数据,FilterOutPutStream向OutputStream中写入数据,在Java 1.1中,相应的有FilterReader和FilterWriter(抽象类,没有子类)用于Decorator模式设计。举个简单的例子:
import java.io.*;
public class DecoratorDemo {
public static void main(String[] args) {
BufferedReader in = new BufferedReader(new FileReader(“FruitList.java”));
String s = new String();
while ((s = in.readLine()) != null)
System.out.println(s);
in.close();
}
}
BufferedReader和FileReader完成了Decorate模式设计,这两个类可以更换为其他具有相同功用的类(在Thinking in Java中称为“修饰器”类)来组合完成特定的任务,正如上文所述,这给开发者提供了多种组合方式,同时也相对的增加了复杂度。
最后,祝blogjava所有成员和Java、开源爱好者元旦快乐!幸福安康!