整理Effective Java書中Item 1: Consider static factory methods instead of constructors心得筆記

主旨

在過去傳統我們所學要取得一個物件,多半是透過該物件所提供建構函式(constructor)new出來,現在書中提出更具優勢的方式來取得物件。

劃重點

把靜態工廠方法(static factory method)直接就字面上意思拆開來看,靜態方法(static method)開發者一般會在Utils class中設計,而看到工廠(factory)字眼就會直接聯想到要製造東西。主要傳達的概念就是透過靜態工廠方法(static factory method)來掌控創建物件而不見得是透過建構函式(constructor),透過此方法有下面幾項優點:

  • 方法(method)是有明確且有意義的名稱,可以讓開發者比直接使用建構函式(constructor)更容易了解功用。就好像是Video video = Video.from("youtube");Video video = new Video("youtube");更直白。

  • 每當要一個新的物件就把它new出來,其實可以想想不一定要生成物件。資源的使用必須是很嚴謹的。這是Boolean的原始碼,使用valueOf獲得Boolean不會需要每次創建Boolean物件。

public static Boolean valueOf(boolean b) {
 return b ? Boolean.TRUE : Boolean.FALSE;
}
  • 透過靜態工廠方法(static factory method)取得子類別物件。返回的型別可以是父類別(superclass),也可以是介面(interface)。
class EmployeeFactory { // super class
    public static Employee hire(String type) {
        switch (type) {
            case 'admin': return new Admin();
            case 'engineer': return new Engineer();
            case 'accountant': return new Accountant();
            default:
                throw new RuntimeException('Wrong employee type');
        }
    }
}
class PaymentFactory { //interface
    public static PaymentGateway create(String type) {
        switch (type) {
            case 'creditcard': return new CreditCardImpl();
            case 'applepay': return new ApplePayImpl();
            case 'cash': return new CachOnDeliveryImpl();
            default:
                throw new RuntimeException('Wrong pay type');
        }
    }
}
  • 讓程式碼更簡潔,像是google guava的Maps.java裡面的newHashMap()
  public static <K, V> HashMap<K, V> newHashMap() {
    return new HashMap<>();
  }

使用如下

// before
Map<String, List<String>> map = new HashMap<String, List<String>>();

// after
Map<String, List<String>> map = Maps.newHashMap();

小結

The static factory method is NOT the same as the Factory Method pattern

看完這小節,雖然要描述主題貌似容易,但其中還有點出不少設計模式以及概念,其他相關還有Singleton, Reflection, ServiceLoader等,後續可以繼續往下深研。

參考延伸閱讀: