<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Java 中的構建器設計模式 > 原文: [https://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/](https://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/) 顧名思義, [**構建器模式**](https://en.wikipedia.org/wiki/Builder_pattern "Builder Pattern")是構建復雜對象的**替代方法**。 僅當您要使用相同的對象構建過程構建不同的不可變對象時,才應使用此方法。 在開始討論之前,我想弄清楚我將在本文中討論的構建器模式**與 GOF“設計模式”書中提到的**稍有不同。 這本書說: 構建器模式是一種設計模式,它允許使用正確的操作順序逐步創建復雜的對象。 構造由導向對象控制,該導向對象僅需要知道要創建的對象的類型。 本書給出如下示例: ![Builder Pattern](https://img.kancloud.cn/dc/4d/dc4d3f66309e2d42987ad1fba236845f_500x171.png) 我真的很難在現實生活中的編程和應用中利用以上示例。 上面的過程與[**抽象工廠**](//howtodoinjava.com/design-patterns/creational/abstract-factory-pattern-in-java/ "Abstract factory pattern in java")模式非常相似(并非完全相似),在該模式中,您找到了特定類型對象的工廠(或構建器),然后工廠為您提供了具體的 該對象的實例。 **這個構建器模式與抽象工廠模式之間唯一的不同之處在于,構建器為您提供了對對象創建過程的更多控制,僅此而已。 除此之外,沒有重大差異。** 一句話,抽象工廠模式是對“`WHAT`”的回答,而構建器模式是對“`HOW`”的回答。 對我來說,構建器模式更像[**流利的接口**](https://en.wikipedia.org/wiki/Fluent_interface "Fluent_interface") 。 通常使用**方法級聯**(或方法鏈接)來實現流利的接口。 現在,從這里開始,我將以我認為在實際情況下特別有用的方式來討論構建器模式。 我也希望說服你們。 ```java Sections in this post: Definition of Builder Pattern Where we need Builder Pattern A sample implementation using Builder Pattern Existing implementations in JDK Benefits and Advantages Costs and Disadvantages Conclusion ``` ## 構建器模式的定義 首先,給構建器模式一個定義: > 構建器模式的目標是“將復雜對象的構造與其表示分開,以便同一構造過程可以創建不同的表示。” ## 我們需要構建器模式的地方 我們已經知道[**不可變**](//howtodoinjava.com/java/related-concepts/how-to-make-a-java-class-immutable/ "How to make a java class immutable")和不可變實例在應用中的好處。 如果對此有任何疑問,請讓我想起 Java 中的`String`類。 正如我已經說過的那樣,構建器模式可以幫助我們創建具有大量狀態屬性的不可變類。 讓我們討論一下我們應用中的一個常見問題。 假設在任何用戶管理模塊中,主要實體都是`User`。 理想情況下,實際上,一旦完全創建了用戶對象,您就不想更改其狀態。 根本沒有道理,對吧? 現在,假設我們的`User`對象具有以下 5 個屬性,即`firstName`,`lastName`,`age`,`phone`和`address`。 在通常的實踐中,如果要創建不可變的`User`類,則必須將所有五個信息作為參數傳遞給構造器。 它看起來像這樣: ```java public User (String firstName, String lastName, int age, String phone, String address){ this.firstName = firstName; this.lastName = lastName; this.age = age; this.phone = phone; this.address = address; } ``` 很好。 現在,如果只有`firstName`和`lastName`是必不可少的,剩下的 3 個字段是可選的,該怎么辦。 問題! 我們需要更多的構造器。 ```java public User (String firstName, String lastName, int age, String phone){ ... } public User (String firstName, String lastName, String phone, String address){ ... } public User (String firstName, String lastName, int age){ ... } public User (String firstName, String lastName){ ... } ``` 我們將需要更多類似上面的內容。 還能管理嗎? 現在,讓我們介紹我們的第六個屬性,即薪水。 現在是問題。 *一種創建更多構造器的方法,另一種方法是放松不變性并引入設置器方法。 您選擇這兩個選項中的任何一個,就松了點,對吧?* 在這里,構建器模式將幫助您使用其他屬性,同時保留 Use 類的不變性。 ## 使用構建器模式的示例實現 下面是我們上面討論的問題的編碼解決方案。 這使用附加的類`UserBuilder`,該類可幫助我們構建具有所有必需屬性和可選屬性組合的所需`User`對象,而不會失去不變性。 ```java public class User { //All final attributes private final String firstName; // required private final String lastName; // required private final int age; // optional private final String phone; // optional private final String address; // optional private User(UserBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.age = builder.age; this.phone = builder.phone; this.address = builder.address; } //All getter, and NO setter to provde immutability public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } public String getPhone() { return phone; } public String getAddress() { return address; } @Override public String toString() { return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address; } public static class UserBuilder { private final String firstName; private final String lastName; private int age; private String phone; private String address; public UserBuilder(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public UserBuilder age(int age) { this.age = age; return this; } public UserBuilder phone(String phone) { this.phone = phone; return this; } public UserBuilder address(String address) { this.address = address; return this; } //Return the finally consrcuted User object public User build() { User user = new User(this); validateUserObject(user); return user; } private void validateUserObject(User user) { //Do some basic validations to check //if user object does not break any assumption of system } } } ``` 下面是方法,我們將在代碼中使用`UserBuilder`: ```java public static void main(String[] args) { User user1 = new User.UserBuilder("Lokesh", "Gupta") .age(30) .phone("1234567") .address("Fake address 1234") .build(); System.out.println(user1); User user2 = new User.UserBuilder("Jack", "Reacher") .age(40) .phone("5655") //no address .build(); System.out.println(user2); User user3 = new User.UserBuilder("Super", "Man") //No age //No phone //no address .build(); System.out.println(user3); } Output: User: Lokesh, Gupta, 30, 1234567, Fake address 1234 User: Jack, Reacher, 40, 5655, null User: Super, Man, 0, null, null ``` 請注意,上面創建的用戶對象**沒有任何設置方法**,因此一旦建立,便無法更改其狀態。 這提供了所需的不變性。 有時,開發人員將屬性添加到`User`類時,可能會忘記為構建器添加對新屬性的支持。 為了最大程度地減少這種情況,我們應該將構建器封裝在它們所構建的類中(如上例所示),以使開發人員更清楚地知道也需要更新一個相關的構建器。 > 有時,我認為應該有一個**驅逐艦模式**(與構建器相對),該模式應該以系統的方式從復雜對象中拆除某些屬性。 你怎么看? ## JDK 中的現有實現 [`java.lang.Appendable`](https://docs.oracle.com/javase/7/docs/api/java/lang/Appendable.html "Appendable") 的所有實現實際上都是在 Java 中使用 Builder 模式的良好示例。 例如: [`java.lang.StringBuilder#append()`](https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html#append%28java.lang.CharSequence%29 "StringBuilder") [未同步的類] [`java.lang.StringBuffer#append()`](https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuffer.html#append%28java.lang.CharSequence%29 "StringBuffer") [同步類] [`java.nio.ByteBuffer#put()`](https://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html#put%28java.nio.ByteBuffer%29 "ByteBuffer")(也在 CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer 和 DoubleBuffer 上) 另一種用法可以在[`javax.swing.GroupLayout.Group#addComponent()`](https://docs.oracle.com/javase/6/docs/api/javax/swing/GroupLayout.Group.html#addComponent%28java.awt.Component%29 "GroupLayout")中找到。 看看這些實現與我們上面討論的相似。 ```java StringBuilder builder = new StringBuilder("Temp"); String data = builder.append(1) .append(true) .append("friend") .toString(); System.out.println(data); Output: Temp1truefriend ``` ## 構建器模式的優點和好處 毫無疑問,在構建器模式中,**代碼行數增加了**至少增加了一倍,但是在**設計靈活性**和更多**可讀代碼**方面,努力得到了回報 。 構造器的**參數被簡化**,并在**高可讀性方法調用**中提供。 構建器模式還有助于最大程度地減少構造器中的參數數量,因此**不需要將可選參數**的`null`傳遞給構造器。 真的吸引了我 另一個好處是,對象總是以`complete`狀態實例化,而不是處于不完整的狀態,直到開發人員調用(如果曾經調用)適當的設置器方法來設置其他字段。 最后,我可以在對象構建過程中構建**不可變對象**,而無需太多復雜的邏輯。 ## 構建器模式的成本與缺點 盡管構建器模式減少了一些代碼行,從而消除了使用設置器方法的需要,但仍然**通過引入構建器對象使總行數**翻了一番。 此外,盡管客戶代碼更具可讀性,但客戶代碼也更為冗長。 雖然對我而言,可讀性比代碼行更重要。 我能想到的唯一缺點。 僅此而已。 如果您也分享您的想法,我會很高興。 **祝您學習愉快!** 參考文獻 [http://en.wikipedia.org/wiki/Builder_pattern](https://en.wikipedia.org/wiki/Builder_pattern) [http://www.javaspecialists.eu/archive/Issue163.html](http://www.javaspecialists.eu/archive/Issue163.html) [http://en.wikipedia.org/wiki/Fluent_interface](https://en.wikipedia.org/wiki/Fluent_interface) [http://martinfowler.com/bliki/FluentInterface.html](http://martinfowler.com/bliki/FluentInterface.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看