实际应用delegate做好api简洁设计——从commons-io排序器想开

我们已经知道,在完成一个通用功能的设计时,必然会抽象并且隔离功能级别,把最一般的功能抽象出来,放到接口里去,具体实现接口的类完成具体功能。因为所有的具体实现都有共同的接口,虽然功能实际不同,但是抽象含义相似,因此在抽象级别,其他类调用时就可以把最抽象的接口作为代理(委托)来调用,思路简单清晰。

在commons-io这个开源框架中,封装了对io的基本操作,其中org.apache.commons.io.comparator包就是经典的设计典范,comparator顾名思义就是为了提供一系列的文件排序器,辅助排序。这里我把结构图画一下:

实际应用delegate做好api简洁设计——从commons-io排序器想开

一个AbstractFileComparator抽象类完成了一层包内抽象,直接实现接口Comparator<File>,并且提供了sort方法完成了通过比较的排序功能:

public File[] sort(File... files) {
        if (files != null) {
            Arrays.sort(files, this);
        }
        return files;
    }

public List<File> sort(List<File> files) {
        if (files != null) {
            Collections.sort(files, this);
        }
        return files;
    }

 

 

 

 

所有的具体排序器实现都继承了这个AbstractFileComparator抽象类,实现compare方法,完成各自的比较,比如有根据文件大小比较的SizeFileComparator,有根据修改时间比较的LastModifiedFileComparator等等。值得一提的就是用到了委托的ReverseComparator和CompositeFileComparator,Reverse顾名思义就是反转排序,默认的排序器都是升序的,谁小把谁排在前面,ReverseComparator通过代理一个Comparator

private final Comparator<File> delegate;

构造时作为参数把delegate实例化,public ReverseComparator(Comparator<File> delegate),最后实现compare方法:

public int compare(File file1, File file2) {
       return delegate.compare(file2, file1); // parameters switched round
   }

完成整个反转排序的功能,看出端倪了吧。一个代理的引入,减少了一半的工作量,把排序功能实现的非常全面。

同理,组合排序器的实现正好利用了多维的代理

private final Comparator<File>[] delegates;

构造时传入的参数是一个可变长度数组,public CompositeFileComparator(Comparator<File>... delegates),或者一个可迭代对象,public CompositeFileComparator(Iterable<Comparator<File>> delegates),实现的compare方法如下:

public int compare(File file1, File file2) {
        int result = 0;
        for (Comparator<File> delegate : delegates) {
            result = delegate.compare(file1, file2);
            if (result != 0) {
                break;
            }
        }
        return result;
    }

组合排序就是提供一系列排序器,顺序比较,直到出现不相等情况。考虑到实际应用,我们经常是否只是实现了Comparable接口,在compareTo方法中写if else呢?引入代理的排序器api设计,给了我们不错的启示。

上一篇:Openstack Restful API 开发框架 Paste + PasteDeploy + Routes + WebOb


下一篇:JS实现是一个文本框(值为参数)输入另一个显示(查询结果)