FilenameFilter:文件名过滤器。这名字起的,没说的,通俗易懂。就是在文件集合中过滤出我想要的文件。
怎么用呢?
我们看一下这个接口怎么写的。
public interface FilenameFilter {
boolean accept(File dir, String name);
}
好家伙!就定义了一个抽象方法,逗我呢?
不要着急!稍后你会看到这个接口和抽象方法的作用。提示:这里会显示出策略模式的强大之处。
我都是以下面这个文件来举例。
现在,我想要在D:\eclipse下找到以 .exe 结尾的文件,看下面我写的代码
public class FilenameFilterDemo {
public static void main(String[] args) {
File file = new File("D:\\eclipse");
//创建一个过滤器实例
FilenameFilterDemo filenameFilterDemo = new FilenameFilterDemo();
FileFilter fileFilter = filenameFilterDemo.new FileFilter();
String[] list = file.list(fileFilter);
for (String string : list) {
System.out.println(string);
}
}
//这是一个内部类过滤器
class FileFilter implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
//String的 endsWith(String str)方法 筛选出以str结尾的字符串
if(name.endsWith(".exe"))
return true;
return false;
}
}
}
结果:
这里我重写了accept()方法,让它能过滤出以 .exe 的文件。
那么这是怎么做到的呢?我们来看list(FilenameFilter filter)的源代码
public String[] list(FilenameFilter filter) {
//将当前File文件夹下的文件名遍历出来
String names[] = list();
/**
* 如果文件夹为空,返回一个空的字符串数组,
* 注意:如果当前文件不是目录,list()方法会返回Null
*/
if ((names == null) || (filter == null)) {
return names;
}
List<String> v = new ArrayList<>();
//从names中取出单个文件的文件名
for (int i = 0 ; i < names.length ; i++) {
/**
* 看到了吗,这里使用了accept(File dir, String name);方法
* 如果过滤到了.exe文件,返回true
* 封装到list集合中
*/
if (filter.accept(this, names[i])) {
v.add(names[i]);
}
}
//将list集合变成数组返回给方法调用者。
return v.toArray(new String[v.size()]);
}
步骤:
首先,会将File目录下的文件集封装到一个数组中。
调用accept()方法,从数组中过滤出符合条件的文件
将符合条件的文件名封装到ArrayList()集合中。
将ArrayList()转换为数组返回给调用者。
那么为什么用到了策略设计模式了呢?
不着急解释。
我再写一个文件过滤器,我想过滤出File表示的目录下 必须是文件 且 文件名长度大于10的文件(怎么这么像绕口令呢?)。
class FileFilter2 implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
if(!dir.isDirectory()){
return false;
}
//我利用dir和name新创建了File对象,不然isFile()和length()不能用
File subfile = new File(dir, name);
if(subfile.isFile()){
if(subfile.length()>10){
return true;
}
}
return false;
}
}
结果:
解析
这里,我定义了两个过滤器 分别是FileFilter 和 FileFilter2。他们都实现了FilenameFileter接口。并重写了accept()方法。注意:list(FilenameFilter filefilter);
参数一直没变,总是filefilter,你会看到,方法内部一直使用的是接口的accept()方法。但将实现类传递进去,内部实际调用的是什么?是实现类FileFilter和FileFilter2的accept()方法。明白了吗?FilenameFilter将list(FilenameFilter filefilter)给欺骗了,list(FilenameFilter filefilter)一直以为方法没变,它仍然是调用接口的accept()方法,但是实际功能已经改变了,只是它不知道而已。没错这就是策略模式的强大之处,欺骗,也可以说是隐藏。 欺骗方法的实际调用者,在实际运行时给他调包。隐藏实现细节,方法调用者不必知道方法是如何实现的,它是谁创建的,以及它具体的功能是什么(我只知道它是用来过滤文件的,过滤什么类型的文件,我也不知道)调用者只需要调用这个方法就行,不必来回改变。灵活度极高。注意:这里使用了接口的解耦合思想,java的多态特性。
在说说另外一个优点:延伸性。
如果需求变了,我想过滤出其他条件的文件。那么,我只需要实现FilenameFileter创建相应的子类,将这个子类传给list(FilenameFilter filefilter);还能查询出你要的文件。是不是延伸性极好?
总结:
想学设计模式的同学,我推荐大家一本书 Head First设计模式,一看就懂,比之这样语诉,图片更能深入人心,理解的也更快。