設計模式-生成器(Builder)

来源:http://www.cnblogs.com/bateman6988/archive/2017/10/11/7616748.html
-Advertisement-
Play Games

一、概念 將一個複雜對像的構建與它的表示分離,使得同樣的構建過程創建不同的表示,又叫建造模式。 生成器模式的重心在於分離構建演算法和具體的構造實現,從而使得構建演算法可以重用。採用不同的構建實現,產生不同的產品。所以生成器模式都會存在以下兩個部分: a.整體構建演算法 b.部件的構造和產品的裝配 二、模式 ...


 一、概念

  將一個複雜對像的構建與它的表示分離,使得同樣的構建過程創建不同的表示,又叫建造模式。

  生成器模式的重心在於分離構建演算法和具體的構造實現,從而使得構建演算法可以重用。採用不同的構建實現,產生不同的產品。所以生成器模式都會存在以下兩個部分:

  a.整體構建演算法

  b.部件的構造和產品的裝配

 

二、模式動機

  生成器模式主要的功能就是構建複雜的產品,且是細化的、分步驟的構建產品,生成器模式重在一步一步解決構造複雜對像的問題。

三、模式的結構

  

  示意代碼:

/**
 * 
* @ClassName: Product 
* @Description: TODO(被構建的產品對像接品) 
* @author beteman6988
* @date 2017年10月1日 上午11:26:33 
*
 */
public interface Product {

}

 

/**
 * 成生器介面,定義構建一個產品對像所需要的各個部件的操作
* @ClassName: Builder 
* @author beteman6988
* @date 2017年10月1日 上午11:28:12 
*
 */
public interface Builder {
    
    /**
     * 構建某個部件
    * @Title: buildPart 
    * @param    
    * @return void    
    * @throws
     */
    public void buildPart();
    
    /**
     * 獲取最終生成的產品對像
    * @Title: getResult 
    * @param @return   
    * @return Product    
    * @throws
     */
    public Product getResult();
}

 

public class ConcreteBuilder implements Builder {

    //最終構建的產品
    private Product resultProduct;

    /**
     * 獲取最終生成的產品
    * @Title: getResult 
    * @param @return   
    * @return Product    
    * @throws
     */
    @Override
    public Product getResult() {
        return this.resultProduct;
    }

    @Override
    public void buildPart() {
        // TODO Auto-generated method stub

    }

}

 

public class Director {
    
    private Builder builder;


    public Director(Builder builder) {
        this.builder = builder;
    }
    
    /**
     * 指導生成器構建最終的產品對像
    * @Title: construct 
    * @param    
    * @return void    
    * @throws
     */
    public void construct() {
        builder.buildPart();
        builder.getResult();
    }

}

 

  a.Builder:生成器介面,定義創建一個Product對像所需要的各個部件的操作。

  b.ConcreteBuilder:具體生成器的實現,實現各個部件的創建,並負責組裝Product對像的各個部件,同時還提供一個讓用戶獲取組裝完畢後的產品對像的方法。

  c.Director:指導者,抽像出來的整體構建演算法,主要用來使用Builder,以一個統一的過程來構建所需要的Product對像。

  d.Product:產品,表示被生成器構建的複雜對像,包含多個部件。

 

四、模式樣例

  以一次台式機組裝經歷為例,當我們去電腦城組裝電腦時,首先導購小妹妹會拿出一張列印好的空白配置報價單,我們在導購小妹的引導下,填寫(當然小導購小妹填寫)完了報價單後,然後組裝工程師小哥就會跟據這個報價單,去倉庫領取所有配件,然後就會將所有的配件組裝在一起,一個完整的computer就組裝好了,最後我們交錢拿電腦走人。

  運用生成器模式對上述過程進行分析:

  a.Product:導購小妹給我們的那個報價單可以說是一臺最終computer product的一個抽像,當我們填寫完一個一個完整的報價單後,可以說一個具體的compueter已經有了,

   不過目前還是一堆零部件,要想得到一臺完整的computer,還需要一個組裝的過程。

  b.Builder:我們的組裝工程師小哥,跟據不同的具體報價單,都要去倉庫忙一翻,要找到所有的部件,可以說只要有報價單,小哥都要將具體產口的每個部件都要找出來,少一個可以說都不行,這個可以說是一個完整電腦每個部件的抽像的建造(只是去倉庫的相關位置拿到相關部件)。

  c.ConcreteBuilder:組裝工程師小哥跟據具體的報價單,去倉庫找到相應的配件,並對每個部件進行處理,該拆封的拆封,該插線的插線,然後依據一定的步驟組裝將所有配件組裝起來,組裝成一臺完整的電腦。

  d.Director:電腦的組裝可以說有固定的套路,可以說這個套路適應於所有的電腦組裝,比如必須先有機箱,然後將主板裝到機箱上,然後將cpu裝到主板上,步驟不能亂。按這個套路,工程師小哥跟據不同的報價單組裝出不同的computer.

   

  代碼如下:

public interface CBuilder {


    /**
     * 構建機箱
    * @Title: buildBox 
    * @param    
    * @return void    
    * @throws
     */
    public void buildBox();

    /**
     * 安裝主板
    * @Title: buildMBoard 
    * @param    
    * @return void    
    * @throws
     */
    public void buildMBoard();

    /**
     * 安裝CPU
    * @Title: buildCpu 
    * @param    
    * @return void    
    * @throws
     */
    public void buildCpu();

    /**
     * 安裝記憶體
    * @Title: buildMemory 
    * @param    
    * @return void    
    * @throws
     */
    public void buildMemory();

    /**
     * 安裝硬碟
    * @Title: buildHDisk 
    * @param    
    * @return void    
    * @throws
     */
    public void buildHDisk();

    /**
     * 返回安裝完畢的電腦
    * @Title: getComputer 
    * @param @return   
    * @return ComputerA    
    * @throws
     */
    public ComputerA getComputer();
}

 

public class ComputerABuilder implements CBuilder {
    
private ComputerA aComputer=new ComputerA();

    @Override
    public void buildBox() {
        this.aComputer.setBox("MAtx");

    }

    @Override
    public void buildMBoard() {
        this.aComputer.setmBoard("AsusMb");

    }

    @Override
    public void buildCpu() {
        this.aComputer.setCpu("Intel CoreI7");

    }

    @Override
    public void buildMemory() {
        this.aComputer.setMemory("King stone DDR4");

    }

    @Override
    public void buildHDisk() {
        this.aComputer.sethDisk("West Hard Disk 1T");

    }

    @Override
    public ComputerA getComputer() {
        // TODO Auto-generated method stub
        
        System.out.println("Box:"+this.aComputer.getBox());
        System.out.println("MBoard:"+this.aComputer.getmBoard());
        System.out.println("Cpu:"+this.aComputer.getCpu());
        System.out.println("Memory:"+this.aComputer.getMemory());
        System.out.println("HDisk:"+this.aComputer.gethDisk());
        
        return aComputer;
    }

}

 

public class ComputerA {

    private String box;
    private String mBoard;
    private String cpu;
    private String memory;
    private String hDisk;

    public ComputerA() {
        super();
    }

    public String getBox() {
        return box;
    }

    public void setBox(String box) {
        this.box = box;
    }

    public String getmBoard() {
        return mBoard;
    }

    public void setmBoard(String mBoard) {
        this.mBoard = mBoard;
    }

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String gethDisk() {
        return hDisk;
    }

    public void sethDisk(String hDisk) {
        this.hDisk = hDisk;
    }

}

 

public class CDirector {
     private CBuilder theCBuilder;
       
       /**
        * @roseuid 59DB89BE02A1
        */
       public CDirector(CBuilder builder) 
       {
           this.theCBuilder=builder;
       }
       
       /**
        * 獨立出來的構建過程
        */
       public void construct() 
       {
           this.theCBuilder.buildBox();
           this.theCBuilder.buildMBoard();
           this.theCBuilder.buildCpu();
           this.theCBuilder.buildMemory();
           this.theCBuilder.buildHDisk();
           this.theCBuilder.getComputer();
        
       }
}

 

public class Client {

    public static void main(String[] args) {
        CBuilder builder=new ComputerABuilder();
        
        CDirector director=new CDirector(builder);
        
        director.construct();
        
    }
}

  運行結果如下:

  Box:MAtx
  MBoard:AsusMb
  Cpu:Intel CoreI7
  Memory:King stone DDR4
  HDisk:West Hard Disk 1T

  

 

五、模式的約束

  對於以下情況應當使用生成器模式:

  1.需要生成的產品對像有複雜的內部結構。每個內部成分可以是一個對像,也可以是產品的一個組成部分。

  2.需要生產的產品的各個部件之間相互依賴,也就是一個部件的建造必須依賴另一個部件建造完成才能建造,生成器模式可以強制實行一種分步驟的建造過程。

  3.在對像的創建過程中會使用到系統中的其它一些對像,這些對像在產品對像的創建過程中不易得到。

六、模式的變體與擴展

  1.省略抽像生成器Builder角色,如果系統確定只會有一個具體生成器角色,那麼就可以省略掉抽像生成器角色,類圖如下:

    

 

  2.省略指導者角色Director :如果抽像生成器Builder角色被省略,如上面的“1.”的情況,那麼Director存在的意義就不大了,該角色也可以進行省略,如下圖:

    

 

 

七、與其它模式的關係

  1.生成器模式與工廠方法模式,這兩個模式可以組合使用。生成器模式的Builder實現中,通常需要選擇具體的部件實現。一個可行的方案就是實現為工廠方法,通常工廠方法來獲取具體的部件對像,然後再進行部件的裝配。

  如下圖:

  

  2.生成器模式與抽像工廠模式,這兩個模式是可以組合使用的,在生成器模式的Builder實現中,需要創建各個部件對像,而這些部件對像是有關聯的,通常是構成的是一個複雜對像的部件對像。也就是說,Builder實現中,需要獲取構成一個複雜對像的產品族,那自然就可以使用抽像工廠模式來實現,這樣一來抽像工廠負責了部件對像的創建,Builder實現裡面則主要負責產品對像的整體構建了。

  如下圖:

  

  其實創建模式和抽像工廠模式兩者還是有區別的,抽像工廠模式的主要目的是創建產品族,這個產品族裡面的單個產品就相當於是構成一個複雜對像的部件對像,抽像工廠對像創建完成後就立即返回整個產品族;而生成器的模式的主要目的是按照構造演算法,一步一步來構建一個複雜的產品對像,通常要等到整個構建過程結速後,才會得到最終的產品對像。

 

八、模式優缺點

   生成器模式可以用同一個構建演算法構建出表現上完全不同的產品,實現產品的構建和產品的表現上的分離。生成器模式正是把產品的構建過程獨立出來,使它和具體產品的表現鬆散耦合,從而使得構建演算法可以重用,而具體產品表現可以擴展和切換,從產品表現維度很好的支持開閉原則。

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 視頻直播是指利用互聯網及流媒體技術進行直播,視頻因融合了圖像、文字、聲音等豐富元素,聲形並茂,效果極佳,逐漸成為互聯網的主流表達方式。初期相關參考:HTTP 長連接和短連接灰度發佈A/B測試今天先到這兒,希望對您在系統架構設計與評估,團隊管理, 項目管理, 產品管理,團隊建設 有參考作用 , 您可能... ...
  • 十一宅了,也沒學習看啥書,所有時間花在了圍棋上,雖然很頹廢,不過令人欣慰的是居然升了3級,現在是6k水平,之前晚上下的多,停在9k挺長時間的,居然在10.1突破了,這麼看來我能升段的目標還是可能實現的,這麼看自信還真是挺重要的,而我一直不算個自信的人,本來打算10.1假期完成這個設計模式總結的,但是 ...
  • 是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織, 在改進和個性化定製界面及用戶交互的同時,不需要重新編寫業務邏輯。M是指業務模型,V是指用戶界面,C則是控制器,使用MVC的目的是將M和V的實現代碼分離, 從 ...
  • A代碼編輯器,線上模版編輯,仿開發工具編輯器,pdf線上預覽,文件轉換編碼B 集成代碼生成器 [正反雙向](單表、主表、明細表、樹形表,快速開發利器)+快速表單構建器 freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表sql腳本,處理類,service等完整模塊C 集成阿 ...
  • 本文會對可能用到的相關技術進行技術選型的說明,以及技術的架構介紹 ...
  • 寫在前面: 第一次配置時好好的,後來第二次改到MVC模式,把依賴註入寫成字典的單例模式時,由於新建的ORM(資料庫映射模型EF),怎麼弄都不用,一直報錯"No connection string named '**Context' could be found in the application ...
  • 什麼是享元模式? 所謂享元模式就是運行共用技術有效地支持大量細粒度對象的復用。系統使用少量對象,而且這些都比較相似,狀態變化小,可以實現對象的多次復用。共用模式是支持大量細粒度對象的復用,所以享元模式要求能夠共用的對象必須是細粒度對象。兩個重要的概念:內部狀態、外部狀態。 內部狀態:在享元對象內部不 ...
  • 首先看一張訪問TT貓首頁的截圖: 測試環境為谷歌瀏覽器,暫且不討論其它瀏覽器,截圖下方我們可以觀察到以下參數: DOMContentLoaded:1.42s | Load:2.31s 以上參數是在CTRL+F5下測試的,也就是說不存在瀏覽器本地緩存一說,DOM渲染時間為1.42s,整個頁面load時 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...