實際應用delegate做好api簡潔設計——從commons-io排序器想開
我們已經知道,在完成一個通用功能的設計時,必然會抽象并且隔離功能級別,把最一般的功能抽象出來,放到接口里去,具體實現接口的類完成具體功能。因為所有的具體實現都有共同的接口,雖然功能實際不同,但是抽象含義相似,因此在抽象級別,其他類調用時就可以把最抽象的接口作為代理(委托)來調用,思路簡單清晰。
在commons-io這個開源框架中,封裝了對io的基本操作,其中org.apache.commons.io.comparator包就是經典的設計典范,comparator顧名思義就是為了提供一系列的文件排序器,輔助排序。這里我把結構圖畫一下:
一個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設計,給了我們不錯的啟示。
posted on 2012-04-28 11:47 changedi 閱讀(1624) 評論(1) 編輯 收藏 所屬分類: Java技術