遞增建構子模式
靜態工廠和建構子在參數眾多時,都難以適當應對。例如,如果類別有 6 個欄位,並且想要在參數為 2 個、3 個…等情況下分別建立建構子,則可以使用以下遞增建構子模式。
但是,即使這樣,如果參數過多,在閱讀程式碼時也可能會混淆每個值的含義,並可能將類型相同的參數混淆並輸入錯誤的值。
Java Bean 模式
Java Bean 模式是使用沒有參數的建構子建立物件,然後呼叫 setter 方法來設定所需參數值的方式。
Java Bean 模式即使參數增加,也能夠避免混淆並建立實體。但是,要建立一個物件,需要呼叫多個 setter 方法,並且在物件完全建立之前,一致性會被破壞。因此,無法使類別成為不可變的。
建構器模式
主要使用兼具遞增建構子模式的穩定性和 Java Bean 模式的可讀性的建構器模式。
用戶端不會直接建立所需的物件,而是呼叫僅包含必需參數的建構子來取得建構器物件。然後,使用建構器物件提供的類似 setter 方法來設定所需的選擇性參數。最後,呼叫沒有參數的 build() 方法來取得所需的物件。
Builder 類別中的建構子只接收必需參數,其餘的選擇性參數則透過類似 setter 方法填入。最後,透過 build() 方法建立完成的 NutritionFactsWithBuilderPattern 物件。NutritionFactsWithBuilderPattern 類別是不可變的,而且建構器的 setter 方法會傳回建構器本身,因此可以連續呼叫。這種方式稱為流暢 API 或方法鏈結。
從用戶端角度來看,透過建構器模式可以輕鬆編寫和閱讀程式碼。
層級設計的類別與建構器模式非常契合
Pizza.Builder 類別是使用遞迴類型限定的泛型類型,並添加了抽象方法 self(),以便子類別在不進行類型轉換的情況下支援方法鏈結。在子類別中,這個抽象方法的傳回值可以是自身。
現在,讓我們看看 Pizza 的子類別紐約披薩和卡爾佐內披薩,體驗建構器模式的靈活性。
每個子類別的建構器定義的 build() 類別都傳回具體的子類別。子類別的方法傳回的類型不是父類別方法傳回的類型,而是其子類型,這項功能稱為協變傳回類型。使用此功能,用戶端無需進行類型轉換。
用戶端可以混合使用 Pizza 的枚舉和每個子類別的枚舉,並透過各自適當的方法完成物件的建立。
建構器模式的缺點
- 需要建立建構器物件。
- 程式碼冗長。
總結
如果建構子或靜態工廠方法需要處理大量參數,請考慮使用建構器模式。
參考資料
- Effective Java
评论0