軟件設計模式學習(七)建造者模式

建造者模式

建造者模式是最複雜的建立型模式,它將客戶端與包含多個組成部分的複雜對象的建立過程分離,客戶端無須知道複雜對象的內部組成部分與裝配部分,只需知道建造者的類型便可。java


模式動機

建造者模式用於建立一個包含對個組成部分的複雜對象,能夠返回一個完整的產品對象給用戶。用戶無須知道建立過程和內部細節,只需直接使用建立好的完整對象便可。好比汽車擁有車輪、方向盤、發送機等各類部件,用戶幾乎不會單獨使用某個部件,而是使用一輛完整的汽車。軟件開發中也存在相似汽車同樣的複雜對象,它們擁有一系列成員屬性,並且可能存在一些限制條件。ide


模式定義

將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。建造者模式是一步一步建立一個複雜對象,容許用戶經過指定複雜對象的類型和內容構建它們,用戶不須要知道內部具體構建細節。函數


模式結構

在這裏插入圖片描述

  1. Builder(抽象建造者)工具

    爲建立Product對象的各個部件指定抽象接口,方法buildPartX()用於建立複雜對象的各個部件;另外一個方法getResult()用於返回複雜對象。測試

  2. ConcreteBuilder(具體建造者)ui

    具體建造者實現Builder接口,實現各部件的構造和裝配方法,定義並明確它所建立的複雜對象,也能夠提供一個方法返回建立好的複雜產品對象。this

  3. Product(產品角色)code

    產品角色是被構建的複雜對象,包含多個組成部件,具體建造者建立該產品的內部表示並定義它的裝配過程。xml

  4. Director(指揮者)對象

    負責安排複雜對象的建造次序,指揮者與抽象建造者之間存在關聯關係,能夠在其construct()建造方法中調用建造者對象的部件構造與裝配方法,完成複雜對象的建造。客戶端只需與指揮者進行交互,在客戶端肯定建造者的類型,並實例化具體建造者對象(也可經過配置文件和反射機制),而後經過指揮者類的構造函數或者set方法將該對象傳入指揮者類中。


建造者模式實例之KFC套餐

  1. 實例說明

    套餐是一個複雜對象,通常包含主食(如漢堡、雞肉卷等)和飲料(若是汁、可樂)等組成部分。不一樣套餐有不一樣的組成部分,KFC服務員根據顧客需求,一步一步裝填這些組成部分,構造一份完整的套餐,而後返回給顧客。

  2. 實例代碼及解釋

    1. 產品類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;
          }
      }
    2. 抽象建造者類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;
          }
      }
    3. 具體建造者類SubMealBuilderA(A套餐建造者類)

      SubMealBuilderA是具體建造者類,用於建立A套餐,它是抽象建造者類的子類,實現了抽象建造者類中聲明的部件的組裝方法。

      public class SubMealBuilderA extends MealBuilder {
      
          @Override
          public void buildFood() {
      
              meal.setFood("一個雞腿堡");
          }
      
          @Override
          public void buildDrink() {
              meal.setDrink("一杯可樂");
          }
      }
    4. 具體建造者類SubMealBuilderB(B套餐建造者類)

      public class SubMealBuilderB extends MealBuilder {
      
          @Override
          public void buildFood() {
      
              meal.setFood("一個雞肉卷");
          }
      
          @Override
          public void buildDrink() {
      
              meal.setDrink("一杯果汁");
          }
      }
    5. 指揮者類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();
          }
      }
    6. 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;
          }
      }
    7. 配置文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <configuration>
         <className>SubMealBuilderA</className>
      </configuration>
    8. 測試類

      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());
          }
      }
    9. 結果分析

      若是在配置文件將節點中內容設置爲 SubMealBuilderA,則輸出結果以下:
      在這裏插入圖片描述
      若是在配置文件將節點中內容設置爲 SubMealBuilderB,則輸出結果以下:
      在這裏插入圖片描述 更換具體建造者無須修改源代碼,只修改配置文件便可。若是須要增長新的具體建造者,只需增長一個新的具體建造者類繼承抽象建造者類,再實現其中聲明的抽象部件組裝方法,修改配置文件,便可使用新的具體建造者構造新的類型的套餐,系統具備良好的靈活性和可擴展性,符合開閉原則的要求。

相關文章
相關標籤/搜索