深入瞭解 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模式
- JavaScript——深入瞭解thisJavaScript
- 深入瞭解機器學習機器學習
- 深入瞭解原型原型
- 深入瞭解 NSURLSessionSession
- Builder 模式UI模式
- Builder模式UI模式
- [譯] 深入瞭解 FlutterFlutter
- 深入瞭解Synchronized原理synchronized
- 深入瞭解babel(一)Babel
- 深入瞭解 Object.definePropertyObject
- 深入瞭解Zookeeper核心原理
- 深入瞭解MySQL的索引MySql索引
- 深入瞭解Object.definePropertyObject
- 深入瞭解Java社群程式Java
- lombok中的builder註解居然是一種設計模式:讓我們瞭解一下“建造者模式”吧LombokUI設計模式
- 深入瞭解解析Https - 從瞭解到放棄HTTP
- 設計模式:Builder模式概述設計模式UI
- 建立模式 03-Builder模式模式UI
- 瞭解模式識別模式
- JavaBean之Builder模式JavaBeanUI模式
- 建造者模式(Builder)模式UI
- Builder設計模式UI設計模式
- Builder模式的理解!!UI模式
- 深入瞭解JavaScript中的物件JavaScript物件
- Nginx深入瞭解-基礎(一)Nginx
- Nginx深入瞭解-基礎(三)Nginx
- 前端進階-深入瞭解物件前端物件
- 深入瞭解 gRPC:協議RPC協議
- 轉載 :深入瞭解ORACLE SCNOracle
- 深入瞭解Oracle資料字典Oracle
- 深入淺出weex-builderUI
- Java設計模式之builder模式Java設計模式UI
- 生成器模式(Builder)模式UI
- 建造者模式(Builder Pattern)模式UI
- 深入瞭解 iOS 的初始化iOS
- 深入瞭解Kafka基本原理Kafka
- OkHttp3深入瞭解之InterceptorsHTTP