建造者模式是最複雜的建立型模式,它將客戶端與包含多個組成部分的複雜對象的建立過程分離,客戶端無須知道複雜對象的內部組成部分與裝配部分,只需知道建造者的類型便可。java
建造者模式用於建立一個包含對個組成部分的複雜對象,能夠返回一個完整的產品對象給用戶。用戶無須知道建立過程和內部細節,只需直接使用建立好的完整對象便可。好比汽車擁有車輪、方向盤、發送機等各類部件,用戶幾乎不會單獨使用某個部件,而是使用一輛完整的汽車。軟件開發中也存在相似汽車同樣的複雜對象,它們擁有一系列成員屬性,並且可能存在一些限制條件。ide
將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。建造者模式是一步一步建立一個複雜對象,容許用戶經過指定複雜對象的類型和內容構建它們,用戶不須要知道內部具體構建細節。函數
Builder(抽象建造者)工具
爲建立Product對象的各個部件指定抽象接口,方法buildPartX()用於建立複雜對象的各個部件;另外一個方法getResult()用於返回複雜對象。測試
ConcreteBuilder(具體建造者)ui
具體建造者實現Builder接口,實現各部件的構造和裝配方法,定義並明確它所建立的複雜對象,也能夠提供一個方法返回建立好的複雜產品對象。this
Product(產品角色)code
產品角色是被構建的複雜對象,包含多個組成部件,具體建造者建立該產品的內部表示並定義它的裝配過程。xml
Director(指揮者)對象
負責安排複雜對象的建造次序,指揮者與抽象建造者之間存在關聯關係,能夠在其construct()建造方法中調用建造者對象的部件構造與裝配方法,完成複雜對象的建造。客戶端只需與指揮者進行交互,在客戶端肯定建造者的類型,並實例化具體建造者對象(也可經過配置文件和反射機制),而後經過指揮者類的構造函數或者set方法將該對象傳入指揮者類中。
套餐是一個複雜對象,通常包含主食(如漢堡、雞肉卷等)和飲料(若是汁、可樂)等組成部分。不一樣套餐有不一樣的組成部分,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,則輸出結果以下:
更換具體建造者無須修改源代碼,只修改配置文件便可。若是須要增長新的具體建造者,只需增長一個新的具體建造者類繼承抽象建造者類,再實現其中聲明的抽象部件組裝方法,修改配置文件,便可使用新的具體建造者構造新的類型的套餐,系統具備良好的靈活性和可擴展性,符合開閉原則的要求。