建造者模式是最復雜的創建型模式,它將客戶端與包含多個組成部分的復雜物件的創建程序分離,客戶端無須知道復雜物件的內部組成部分與裝配部分,只需知道建造者的型別即可,
模式動機
建造者模式用于創建一個包含對個組成部分的復雜物件,可以回傳一個完整的產品物件給用戶,用戶無須知道創建程序和內部細節,只需直接使用創建好的完整物件即可,比如汽車擁有車輪、方向盤、發送機等各種部件,用戶幾乎不會單獨使用某個部件,而是使用一輛完整的汽車,軟體開發中也存在類似汽車一樣的復雜物件,它們擁有一系列成員屬性,而且可能存在一些限制條件,
模式定義
將一個復雜物件的構建與它的表示分離,使得同樣的構建程序可以創建不同的表示,建造者模式是一步一步創建一個復雜物件,允許用戶通過指定復雜物件的型別和內容構建它們,用戶不需要知道內部具體構建細節,
模式結構

-
Builder(抽象建造者)
為創建Product物件的各個部件指定抽象介面,方法buildPartX()用于創建復雜物件的各個部件;另一個方法getResult()用于回傳復雜物件,
-
ConcreteBuilder(具體建造者)
具體建造者實作Builder介面,實作各部件的構造和裝配方法,定義并明確它所創建的復雜物件,也可以提供一個方法回傳創建好的復雜產品物件,
-
Product(產品角色)
產品角色是被構建的復雜物件,包含多個組成部件,具體建造者創建該產品的內部表示并定義它的裝配程序,
-
Director(指揮者)
負責安排復雜物件的建造次序,指揮者與抽象建造者之間存在關聯關系,可以在其construct()建造方法中呼叫建造者物件的部件構造與裝配方法,完成復雜物件的建造,客戶端只需與指揮者進行互動,在客戶端確定建造者的型別,并實體化具體建造者物件(也可通過組態檔和反射機制),然后通過指揮者類的建構式或者set方法將該物件傳入指揮者類中,
建造者模式實體之KFC套餐
-
實體說明
套餐是一個復雜物件,一般包含主食(如漢堡、雞肉卷等)和飲料(如果汁、可樂)等組成部分,不同套餐有不同的組成部分,KFC服務員根據顧客需求,一步一步裝填這些組成部分,構造一份完整的套餐,然后回傳給顧客,
-
實體代碼及解釋
-
產品類Meal
套餐Meal是復雜產品物件,它包括兩個成員屬性food和drink,其中food表示主食,drink表示飲料,Meal中還包括成員屬性的Getter方法和Setter方法,
public class Meal { //部件 private String food; private String drink; public String getDrink() { return drink; } public void setDrink(String drink) { this.drink = drink; } public String getFood() { return food; } public void setFood(String food) { this.food = food; } } -
抽象建造者類MealBuilder(套餐建造者類)
MealBuilder是套餐建造者,它是一個抽象類,宣告了抽象的部件組裝方法buildFood()和buildDrink(),在MealBuilder中定義Meal型別的物件meal,提供工廠方法getMeal()用于回傳meal物件,
public abstract class MealBuilder { protected Meal meal = new Meal(); public abstract void buildFood(); public abstract void buildDrink(); public Meal getMeal() { return meal; } } -
具體建造者類SubMealBuilderA(A套餐建造者類)
SubMealBuilderA是具體建造者類,用于創建A套餐,它是抽象建造者類的子類,實作了抽象建造者類中宣告的部件的組裝方法,
public class SubMealBuilderA extends MealBuilder { @Override public void buildFood() { meal.setFood("一個雞腿堡"); } @Override public void buildDrink() { meal.setDrink("一杯可樂"); } } -
具體建造者類SubMealBuilderB(B套餐建造者類)
public class SubMealBuilderB extends MealBuilder { @Override public void buildFood() { meal.setFood("一個雞肉卷"); } @Override public void buildDrink() { meal.setDrink("一杯果汁"); } } -
指揮者類KFCWaiter(服務員類)
KFCWaiter類是指揮者類,在KFC套餐制作程序中相當于KFC服務員,客戶端指定具體建造者型別,在其construct()方法中呼叫指定建造者物件的部件組裝方法和工廠方法,
public class KFCWaiter { private MealBuilder mealBuilder; public void setMealBuilder(MealBuilder mealBuilder) { this.mealBuilder = mealBuilder; } public Meal construct() { mealBuilder.buildFood(); mealBuilder.buildDrink(); return mealBuilder.getMeal(); } } -
XML操作工具類
public class XMLUtil { public static Object getBean() throws Exception { //創建決議器工廠 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); //創建決議器 DocumentBuilder builder = builderFactory.newDocumentBuilder(); //得到document Document document = builder.parse("config.xml"); //獲取包含品牌名稱的文本節點 NodeList brandNameList = document.getElementsByTagName("className"); Node classNode = brandNameList.item(0).getFirstChild(); String className = classNode.getNodeValue().trim(); Class c = Class.forName("com.builderPattern." + className); Object o = c.newInstance(); return o; } } -
組態檔
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <className>SubMealBuilderA</className> </configuration> -
測驗類
public class Test { public static void main(String[] args) throws Exception { //動態確定套餐種類 MealBuilder mealBuilder = (MealBuilder) XMLUtil.getBean(); //服務員是指揮者 KFCWaiter waiter = new KFCWaiter(); //服務員準備套餐 waiter.setMealBuilder(mealBuilder); //客戶獲得套餐 Meal meal = waiter.construct(); System.out.println("套餐組成:"); System.out.println(meal.getDrink()); System.out.println(meal.getFood()); } } -
結果分析
如果在組態檔將節點中內容設定為 SubMealBuilderA,則輸出結果如下:

如果在組態檔將節點中內容設定為 SubMealBuilderB,則輸出結果如下:

更換具體建造者無須修改源代碼,只修改組態檔即可,如果需要增加新的具體建造者,只需增加一個新的具體建造者類繼承抽象建造者類,再實作其中宣告的抽象部件組裝方法,修改組態檔,即可使用新的具體建造者構造新的型別的套餐,系統具有良好的靈活性和可擴展性,符合開閉原則的要求,
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/83455.html
標籤:其他
