天天看點

實際應用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) {

            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設計,給了我們不錯的啟示。