深入瞭解 Builder 模式 - frankel
使用 Builder 模式的一個常見實現是擁有一個流暢的介面,以下為呼叫者程式碼:
Person person = new PersonBuilder().withFirstName("John").withLastName("Doe").withTitle(Title.MR).build(); |
可以透過以下構建器啟用此程式碼段:
public class PersonBuilder { private Person person = new Person(); public PersonBuilder withFirstName(String firstName) { person.setFirstName(firstName); return this; } // Other methods along the same model // ... public Person build() { return person; } } |
Builder 的工作完成了:Person例項被很好地封裝,只有build()方法最終返回構建的例項。這通常是大多數文章停止的地方,假裝已經涵蓋了該主題。不幸的是,可能會出現一些需要更深入研究的情況。
假設我們需要一些驗證來處理最終Person例項,例如該lastName屬性是強制性的。為了提供這一點,我們可以輕鬆檢查該屬性是否null在build()方法中並相應地丟擲異常。
public Person build() { if (lastName == null) { throw new IllegalStateException("Last name cannot be null"); } return person; } |
當然,這解決了我們的問題。不幸的是,這種檢查發生在執行時,因為呼叫我們的程式碼的開發人員會發現(讓他們非常懊惱)。為了走向真正的 DSL,我們必須更新我們的設計——很多。我們應該強制執行以下呼叫者程式碼:
Person person1 = new PersonBuilder().withFirstName("John").withLastName("Doe").withTitle(Title.MR).build(); // OK Person person2 = new PersonBuilder().withFirstName("John").withTitle(Title.MR).build(); // Doesn't compile |
我們必須更新我們的構建器,以便它可以返回自身,或者返回一個缺少build()方法的無效構建器。
轉化為以下程式碼更好:
public class PersonBuilder { private Person person = new Person(); public InvalidPersonBuilder withFirstName(String firstName) { person.setFirstName(firstName); return new InvalidPersonBuilder(person); } public ValidPersonBuilder withLastName(String lastName) { person.setLastName(lastName); return new ValidPersonBuilder(person); } // Other methods, but NO build() methods } public class InvalidPersonBuilder { private Person person; public InvalidPersonBuilder(Person person) { this.person = person; } public InvalidPersonBuilder withFirstName(String firstName) { person.setFirstName(firstName); return this; } public ValidPersonBuilder withLastName(String lastName) { person.setLastName(lastName); return new ValidPersonBuilder(person); } // Other methods, but NO build() methods } public class ValidPersonBuilder { private Person person; public ValidPersonBuilder(Person person) { this.person = person; } public ValidPersonBuilder withFirstName(String firstName) { person.setFirstName(firstName); return this; } // Other methods // Look, ma! I can build public Person build() { return person; } } |
這是一個巨大的改進,因為現在開發人員可以在編譯時知道他們構建的物件是無效的。
下一步是想象更復雜的用例:
- 必須按特定順序呼叫構建器方法。例如,房子應該有地基、框架和屋頂。建造框架需要建造地基,就像建造屋頂需要框架一樣。
- 更復雜的是,有些步驟取決於之前的步驟(例如,只有使用混凝土框架才能擁有平屋頂)
相關文章
- Builder 模式UI模式
- 深入瞭解原型原型
- 深入瞭解ConcurrentHashMapHashMap
- JavaScript——深入瞭解thisJavaScript
- 深入瞭解babel(一)Babel
- [譯] 深入瞭解 FlutterFlutter
- 深入瞭解Synchronized原理synchronized
- 深入瞭解SCN(轉)
- lombok中的builder註解居然是一種設計模式:讓我們瞭解一下“建造者模式”吧LombokUI設計模式
- 建立模式 03-Builder模式模式UI
- 設計模式:Builder模式概述設計模式UI
- 建造者模式(Builder)模式UI
- JavaBean之Builder模式JavaBeanUI模式
- 深入瞭解解析Https - 從瞭解到放棄HTTP
- 深入淺出weex-builderUI
- 深入瞭解Object.definePropertyObject
- 深入瞭解MySQL的索引MySql索引
- 深入瞭解 Object.definePropertyObject
- 深入瞭解Zookeeper核心原理
- Java設計模式之builder模式Java設計模式UI
- 設計模式-建造者模式(Builder)設計模式UI
- 建造者模式(Builder Pattern)模式UI
- 生成器模式(Builder)模式UI
- 瞭解模式識別模式
- 設計模式--建造者模式(Builder Pattern)設計模式UI
- 【設計模式筆記】(二)- Builder模式設計模式筆記UI
- 設計模式-生成器模式Builder設計模式UI
- 【設計模式】- 生成器模式(Builder)設計模式UI
- 深入瞭解JavaScript中的物件JavaScript物件
- 前端進階-深入瞭解物件前端物件
- Nginx深入瞭解-基礎(一)Nginx
- Nginx深入瞭解-基礎(三)Nginx
- 深入瞭解機器學習機器學習
- 深入瞭解SpringMVC原始碼解析SpringMVC原始碼
- 構建者模式(Builder pattern)模式UI
- Builder模式與Java語法UI模式Java
- Builder模式,今天你用了嘛UI模式
- 《設計模式》 - 3. 建立者模式( Builder )設計模式UI