因爲靜態工廠和構造器有個共同的侷限性:它們都不能很好地擴展到大量的可選參數。所以咱們下面要來講說構建器,所謂的構建器其實就是具備建立外部類功能的內部靜態類。首先咱們先理解幾個模式java
1.重疊構造器模式安全
提供一個只有必要參數的構造器,第二個構造器有一個可選參數,第三個構造器有兩個可選參數,依次類推,直到最後一個構造器包含全部的可選參數。多線程
缺點:誰做爲第一個可選參數是一個問題,由於後一個包含兩個可選參數的構造器必須傳遞值給第一個可選參數,致使須要設置許多本不想設置的參數。併發
2.JavaBean模式高併發
經過一個無參構造器建立對象,而後調用setter方法來設置每一個必要的參數。這樣建立實例很容易,產生的代碼讀起來也比較容易,由於經過setter的方法名能知道設置的參數是哪個。ui
缺點:構造過程被分到了幾個調用之中,在構造過程當中沒法保證JavaBean的一致性。this
3.Builder模式(本條主要)spa
不直接生成想要的對象,而是讓客戶利用全部必要的參數調用構造器,獲得一個builder對象,而後客戶端在builder對象上調用相似於setter的方法設置每一個可選參數,最後,客戶端調用無參的build方法來生成不可變的對象。線程
好了,下面就讓咱們來看看具體的構建器的作法:設計
public class BuilderObject { private final String filed01; private final String filed02; private final String filed03; private final String filed04; private BuilderObject(Builder builder){ this.filed01 = builder.filed01; this.filed02 = builder.filed02; this.filed03 = builder.filed03; this.filed04 = builder.filed04; } //構建器(內部類) public static class Builder{ private String filed01; private String filed02; private String filed03; private String filed04; public Builder filed01(String filed01){ this.filed01 = filed01; return this; } public Builder filed02(String filed02){ this.filed02 = filed02; return this; } public Builder filed03(String filed03){ this.filed03 = filed03; return this; } public Builder filed04(String filed04){ this.filed04 = filed04; return this; } public BuilderObject build(){//build方法,生成一個須要被構建的類 return new BuilderObject(this); } } }
使用的時候咱們只須要按照本身的意願來添加便可:
BuilderObject builderObject = new BuilderObject.Builder() .filed01("filed01") .filed02("filed02") .filed03("filed03") .filed04("filed04") .build();
那咱們應該在何時使用構建器呢?若是有一個類有不少個參數filed0一、filed0二、filed0三、filed0四、filed0五、filed06......其中有些必填有些非必填。這時候咱們若是選擇構造器(咱們少選點參數來舉例,就選擇filed0一、filed0二、filed03,其中就filed01必填,另外兩個選填)的話,就以下:
public MyObject(String filed01, String filed02, String field03) { this.filed01 = filed01; this.filed02 = filed02; this.field03 = field03; } public MyObject(String filed01, String filed02) { this(filed01, filed02, null); } public MyObject(String filed01) { this(filed01, null, null); }
那麼若是有更多的參數就須要更多的構造方法了,顯然很不科學。同理靜態工廠方法也是不合理的,這時候有人可能會說,用Javabean方式不就能夠了麼?給每一個屬性設置setter/getter方法,看似好像這種方法好像解決了上述問題,可是!javabean模式有一個致命的缺陷,就是它的構造過程分部到幾回調用中,而不是一次性完成的。也就是說三個字段我須要使用三次setter方法,而不是一次性完成。這意味着什麼呢?意味着它有可能在構造的過程當中被改變,這一點在多線程、高併發的程序中顯得尤其重要。不只如此,javabean模式還有第二個缺點:若是對象中含有final修飾的字段,那麼javabean模式將不能對其執行setter操做。
總結:
若是類的構造器或是靜態工廠方法中具備多個參數,設計這種類時,使用Builder方式(構建器方式)就是種不錯的選擇,特別是當大可能是參數都是可選的時候。與使用傳統的重疊構造器模式相比,使用Builder模式的客戶端代碼將更容易閱讀和編寫,構建器也比javabean更加安全。