Builder建造者模式將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。Builder模式是一步一步建立一個複雜的對象,它容許用戶能夠只經過指定複雜對象的類型和內容就能夠構建它們,用戶不須要了解所構建對象的內部具體構建細節,Builder建造設計模式的目的是爲了將構造複雜對象的過程和它的部件解耦。 java
Builder建造者設計模式中有兩個重要角色:Director指導者和Builder建造者。Director指導者至關於設計師或架構師,擁有整個產品各個部件之間關係的構建藍圖。Builder建造者是部件的具體建立者,Builder建造者根據Director指導者的指示建立產品的各個部件,最終由Director構建出完整產品。Builder建造者設計模式的UML圖以下: 設計模式
《Effective java》中有一個關於建造者模式的例子以下: 安全
用一個類表示包裝食品外面顯示的養分成分,其中每份含量和每罐含量是必須的,卡洛里,脂肪,納和碳水化合物是可選參數。
你們通常習慣使用重載構造方法來解決該問題,代碼以下: 架構
public class NutritionFacts{ //必須參數 private final int servingSize; private final int servings; //可選參數 private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public NutritionFacts(int servingSize, int servings){ this(servingSize, servings, 0); } public NutritionFacts(int servingSize, int servings, int calories){ this(servingSize, servings, calories, 0); } public NutritionFacts(int servingSize, int servings, int calories, int fat){ this(servingSize, servings, calories, fat, 0); } public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium){ this(servingSize, servings, calories, fat, sodium, 0); } public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate){ this.servingSize = servingSize; this.servings = servings; this.calories = calories; this.fat = fat; this.sodium = sodium; this.carbohydrate = carbohydrate; } }
若是想要建立實例對象的時候,就利用參數列表最短的構造方法: app
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);若是可選參數不少的時候就難以控制,客戶端代碼變得很難編寫,且難以閱讀,若是不當心參數順序混淆了,在編譯的時候很難發現問題,在運行時出錯時難以調試。
public class NutritionFacts{ //必須參數 private int servingSize = -1; private int servings = -1; //可選參數 private int calories = 0; private int fat = 0; private int sodium = 0; private int carbohydrate = 0; public NutritionFacts(){} public void setServingSize(int val){ this.servingSize = val; } public void setServings(int val){ this.servings = val; } public void setCalories(int val){ this.calories = val; } public void setFat(int val){ this.fat = val; } public void setSodium(int val){ this.sodium = val; } public void setCarbohydrate(int val){ this.carbohydrate = val; } }使用setter方法能夠彌補重載構造方法的缺陷,建立實例對象很容易,而且代碼也容易閱讀:
NutritionFacts cocaCola = new NutritionFacts(); cocaCola.setServingSize(240); cocaCola.setServings(8); cocaCola.setCalories(100); cocaCola.setFat(27);因爲javaBean自身有着很嚴重的缺點,構造過程被分到了幾個調用中,在構造過程當中java Bean可能處於不一致的狀態,類沒法僅僅經過檢驗構造方法參數的有效性來保證一致性,使用處於不一致狀態的對象將會致使失敗。另外javaBean阻止了把類作成不可變的可能,所以很難確保線程安全。
public class NutritionFacts{ //必須參數 private final int servingSize; private final int servings; //可選參數 private final int calories; private final int fat; private final int sodium; private final int carbohydrate; //建造者 public static class Builder{ //必須參數 private final int servingSize; private final int servings; //可選參數 private final int calories = 0; private final int fat = 0; private final int sodium = 0; private final int carbohydrate = 0; public Builder(int servingSize, int servings){ this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val){ this.calories = val; return this; } public Builder fat(int val){ this.fat = val; return this; } public Builder sodium(int val){ this.sodium = val; return this; } public Builder carbohydrate(int val){ this.carbohydrate = val; return this; } public NutritionFacts build(){ return new NutritionFacts(this); } } private NutritionFacts(Builder builder){ this.servingSize = builder.servingSize; this.servings = builder.servings; this.calories = builder.calories; this.fat = builder.fat; this.sodium = builder.sodium; this.carbohydrate = builder.carbohydrate; } }使用建造者模式建立實例對象:
NutritionFacts cocaCola = new NutritionFacts().Build(240, 8).calories(100).sodium(35).carbohydrate(27).build();建造者模式能夠有多個可變參數,能夠利用建造器構建多個對象,參數能夠在建立時動態調整。
Builder建造者模式和AbstraceFactory抽象工廠模式的區別: ui
Builder建造者模式和AbstraceFactory抽象工廠模式很是相似,不少人常常分不清楚,區別以下: this
(1).抽象工廠模式中,每一次工廠物件被呼叫時都會傳回一個完整的產品物件,而使用端有可能會決定把這些產品組裝成一個更大的和複雜的產品,也有可能不會。工廠物件是沒有狀態的,不知道上一次構建的是哪個產品,也沒有將來的概念,不知道下一次構建的是哪個產品,更不知道本身構建的產品在更高層的產品結構藍圖中是什麼位置。換言之,雖然抽象工廠模式與建造模式都是設計模式,可是抽象工廠模式處在更加具體的尺度上,而建造模式則處於更加宏觀的尺度上。一個系統能夠由一個建造模式和一個抽象工廠模式組成,使用端經過呼叫這個導演角色,間接地呼叫另外一個抽象工廠模式的工廠角色。工廠樣式傳回不一樣產品族的零件,而建造者模式則把它們組裝起來。 spa
JDK中建造者模式的應用: 線程
StringBuilder和StringBuffer的append()方法使用了建造者模式。 設計