我們已經知道,在完成一個通用功能的設計時,必然會抽象并且隔離功能級别,把最一般的功能抽象出來,放到接口裡去,具體實作接口的類完成具體功能。因為所有的具體實作都有共同的接口,雖然功能實際不同,但是抽象含義相似,是以在抽象級别,其他類調用時就可以把最抽象的接口作為代理(委托)來調用,思路簡單清晰。
在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) {
collections.sort(files, this);
所有的具體排序器實作都繼承了這個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方法如下:
int result = 0;
for (comparator<file> delegate : delegates) {
result = delegate.compare(file1, file2);
if (result != 0) {
break;
}
return result;
組合排序就是提供一系列排序器,順序比較,直到出現不相等情況。考慮到實際應用,我們經常是否隻是實作了comparable接口,在compareto方法中寫if else呢?引入代理的排序器api設計,給了我們不錯的啟示。