使用Java 8 Lambda簡化Decorator設計模式

張益裕 Michael Chang

  • 恆逸教育訓練中心-資深講師
  • 技術分類:程式設計

 

 

如果你需要針對陣列或List裡面的字串資料進行排序,需求是先依照字元個數排序,
如果字元個數一樣,再依照字串內容排序,你可以宣告一個像這樣的類別:

public class StringLengthComparator implements Comparator {
    @Override
    public int compare(String s1, String s2) {
        if (s1.length() != s2.length()) {
            return s1.length() - s2.length();
        }
        else {
            return s1.compareTo(s2);
        }
    }
}

在排序字串的時候,如果需要考慮null值,而且把null值放在最前面,為了可以靈活的應用在其它物件的排序,所以你會套用decorator pattern,宣告一個下面的類別:

public class NullDecoratorComparator implements Comparator {
    
    private Comparator com;
    public NullDecoratorComparator(Comparator com) {
        this.com = com;
    }
    @Override
    public int compare(T s1, T s2) {
        if (s1 == null || s2 == null) {
            return s1 == null ? -1 : 1;
        }
        return com.compare(s1, s2);
    }
}

設計好需要的類別以後,就可以使用它們為你的資料執行排序的工作:

StringLengthComparator slc = new StringLengthComparator();
List kws = Arrays.asList(
                "match", "if", "char", "hash", "assert", "enum", "long");
kws.sort(slc);
// if,char,enum,hash,long,match,assert
NullDecoratorComparator ndc = new NullDecoratorComparator( slc );
List kws2 = Arrays.asList(
                "match", "if", "char", "hash", "assert", "enum", "long", null);
kws2.sort(ndc);
// null,if,char,enum,hash,long,match,assert

上面的作法應該是清楚而且靈活的設計,不過從Java 8開始,你可以使用Lambda的特性,讓這類的設計更加簡化。提供同樣的功能與靈活性,使用Lambda的設計會像這樣:

public static Comparator getStringLengthComparator() {
    return (s1, s2) -> {
        if (s1.length() != s2.length()) {
            return s1.length() - s2.length();
        }
        else {
            return s1.compareTo(s2);
        }
    };
}
public static  Comparator getNullDecoratorComparator(Comparator com) {
    return (s1, s2) -> {
        if (s1 == null || s2 == null) {
            return s1 == null ? -1 : 1;
        }
        return com.compare(s1, s2);
    };
}

不只是設計與維護可以比傳統的作法好一些,使用的時候也更簡單了:

List kws3 = Arrays.asList(
        "match", "if", "char", "hash", "assert", "enum", "long");        
kws3.sort( getStringLengthComparator() );
// if,char,enum,hash,long,match,assert
List kws4 = Arrays.asList(
        "match", "if", "char", "hash", "assert", "enum", "long", null);
kws4.sort( getNullDecoratorComparator( getStringLengthComparator() ) );
// null,if,char,enum,hash,long,match,assert