設計模式(4)建造者模式/生成器模式(Builder)

来源:http://www.cnblogs.com/fonour/archive/2017/08/24/7412450.html
-Advertisement-
Play Games

設計模式(0)簡單工廠模式 設計模式(1)單例模式(Singleton) 設計模式(2)工廠方法模式(Factory Method) 設計模式(3)抽象工廠模式(Abstract Factory) 源碼地址 0 建造者模式簡介 0.0 建造者模式定義 建造者模式是一種常見的創建型模式,也稱生成器模式 ...


設計模式(0)簡單工廠模式

設計模式(1)單例模式(Singleton)

設計模式(2)工廠方法模式(Factory Method)

設計模式(3)抽象工廠模式(Abstract Factory)

源碼地址

0 建造者模式簡介

0.0 建造者模式定義

建造者模式是一種常見的創建型模式,也稱生成器模式。建造者模式的一般書面化定義為:將一個複雜對象的構建與該對象的表示分離,使得同樣的構建過程可以創建不同的表示

建造者模式主要用於構建複雜產品,並且該產品是可以步驟化或者模塊化的,最終可以根據步驟或模塊組裝創建出一個複雜產品。

現實生活中我們每天都在使用的手機有不同品牌不同型號,千差萬別,但他們都具有屏幕、電池、外殼、核心(CPU、GUPU、ROM、RAM等)共性模塊,即他們的創建過程是一致的,變化的只是每個步驟/模塊的詳細實現細節。這種情景是使用創建者模式的最佳時機,最終產品構建過程是統一且固定的,我們將變化的部分交給建造者,只需要配置不同的建造者,就可以使同樣的構建過程生產出完全不同的產品。

建造者模式的結構圖如下

103735-21dae004efea8394

Director:指導者,主要用來使用Buider介面,以一個統一固定的過程生產最終的產品Product

Builder:建造者抽象介面,定義創建一個Product對象所需各個部件的操作。在該介面中一般要求包含創建部件的方法如buidPartA,buidPartB等,同時還要包含一個獲取最終創建的複雜對象的方法getResult()。builder可以定義為一個抽象類或者介面

ConcreteBuilder:具體的建造者實現,繼承自Builder介面,實現介面中定義的創建部件及返回產品的方法。在這裡不同的創建者實現類,對同一部件或步驟進行不同的詳細實現,來完成不同產品的創建。

Product:最終產品類,表示被建造者構建出來的複雜對象,其用於多個固定的部件或步驟。

0.1 建造者模式應用場景

我們以英雄祭壇里造英雄這一過程為例。在使用模式之前,我們最直接的代碼應該像下麵這樣。

惡魔獵手創建類

/// <summary>
/// 惡魔獵手創建類
/// </summary>
public class DH
{
    /// <summary>
    /// 創建英雄
    /// </summary>
    /// <returns></returns>
    public string BuilderHero()
    {
       string body = "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; // 創建身體
        string weapon = "艾辛諾斯雙刃。"; // 創建武器
        string mount = "我有這雙腳有這雙腿。"; // 創建坐騎
        return body + weapon + mount;
    }
}

同樣,月之女祭司創建類

/// <summary>
/// 月之女祭司創建類
/// </summary>
public class POM
{
    /// <summary>
    /// 創建英雄
    /// </summary>
    /// <returns></returns>
    public string BuilderHero()
    {
       string body = "夜幕只為朱顏改,群星隕落無窮。"; // 創建身體
        string weapon = "索利達爾·群星之怒。"; // 創建武器
        string mount = "艾斯卡達爾。"; // 創建坐騎
        return body + weapon + mount;
    }
}

客戶調用時只需要實例化不同的英雄創建類,來完成對應英雄的創建。

DH dh = new DH();
Console.WriteLine(dh.BuilderHero());
POM pom = new POM();
Console.WriteLine(pom.BuilderHero());
Console.ReadLine();

這樣我們需要別的英雄時只需要再添加一個創建該英雄對應的類。

我們這裡只是簡單的通過一句話描述創建了英雄身體、武器、坐騎三個關鍵部位,而實際中一個複雜產品的構件過程是遠遠要複雜的多,比如我們常見的文件導出,一個文件有頭、內容、尾部說明三類內容,導出txt格式跟導出xml格式的操作,每個部位的創建都要根據不同的格式進行處理。

同時我們發現這樣一種情況,每個英雄創建類中創建英雄的方法其實都是同一種模式,處理步驟完全一樣,唯一變化的部分就在於每個步驟的具體實現細節,我們自然會考慮

1、創建每個英雄都要用到同樣的步驟,對與固定不變的部分,我們要提煉出來,形成統一且公用的處理過程

2、英雄不只這兩個,還會有很多其他英雄需要創建,要求我們在處理過程不變的情況下,能實現創建不同英雄的需要

也就是說,我們的固定不變的處理過程應該和變化的具體實現分離,從而達到固定處理過程的復用,同時還能滿足不同具體實現的需求,此時的需求已經和前面介紹過的建造者模式非常貼近了。

1 建造者模式詳解

0、提煉具體產品類

將上面用字元串表示的英雄的三個特征使用一個英雄類表示

/// <summary>
/// 英雄類
/// </summary>
public class Hero
{
    /// <summary>
    /// 身體特征
    /// </summary>
    public string Body { get; set; }

    /// <summary>
    /// 武器
    /// </summary>
    public string Weapon { get; set; }

    /// <summary>
    /// 坐騎
    /// </summary>
    public string Mount { get; set; }
}

1、建造者介面

建造者介面包含創建各部位的方法定義,及獲取最終產品方法的定義

/// <summary>
/// 建造者介面
/// </summary>
public interface IBuilder
{
    /// <summary>
    /// 創建身體特征
    /// </summary>
    /// <returns></returns>
    void BuildBody();

    /// <summary>
    /// 創建武器
    /// </summary>
    /// <returns></returns>
    void BuildWepon();

    /// <summary>
    /// 創建坐騎
    /// </summary>
    /// <returns></returns>
    void BuildMount();

    /// <summary>
    /// 獲取最終產品
    /// </summary>
    /// <returns></returns>
    Hero GetResult();
}

2、建造者具體實現類

惡魔獵手建造者實現類

/// <summary>
/// 惡魔獵手建造者實現類
/// </summary>
public class DHBuilder : IBuilder
{
    private Hero _hero = new Hero();

    /// <summary>
    /// 創建身體特征
    /// </summary>
    /// <returns></returns>
    public void BuildBody()
    {
        _hero.Body = "黑夜給了我黑色眼睛,我卻用它去尋找光明。";
    }

    /// <summary>
    /// 創建武器
    /// </summary>
    /// <returns></returns>
    public void BuildWeapon()
    {
        _hero.Weapon= "艾辛諾斯雙刃。";
    }

    /// <summary>
    /// 創建坐騎
    /// </summary>
    /// <returns></returns>
    public void BuildMount()
    {
        _hero.Mount= "我有這雙腳有這雙腿。";
    }

    public Hero GetResult()
    {
        return _hero;
    }
}

月之女祭司建造者類實現

/// <summary>
/// 月之女祭司建造者類
/// </summary>
public class POMBuilder : IBuilder
{
    private Hero _hero = new Hero();

    /// <summary>
    /// 創建身體特征
    /// </summary>
    /// <returns></returns>
    public void BuildBody()
    {
        _hero.Body = "夜幕只為朱顏改,群星隕落無窮。";
    }

    /// <summary>
    /// 創建武器
    /// </summary>
    /// <returns></returns>
    public void BuildWeapon()
    {
        _hero.Weapon = "索利達爾·群星之怒。";
    }

    /// <summary>
    /// 創建坐騎
    /// </summary>
    /// <returns></returns>
    public void BuildMount()
    {
        _hero.Mount = "艾斯卡達爾。";
    }

    /// <summary>
    /// 創建最終產品
    /// </summary>
    /// <returns></returns>
    public Hero GetResult()
    {
        return _hero;
    }

}

3 、指導者實現

/// <summary>
/// 指導者
/// </summary>
public class Director
{
    /// <summary>
    /// 指導方法
    /// </summary>
    public void Construct(IBuilder builder)
    {
       builder.BuildBody(); // 創建身體特征
        builder.BuildWeapon(); // 創建武器
        builder.BuildMount(); // 創建坐騎
    }
}

4、客戶端調用

Director director = new Director();

DHBuilder buider1 = new DHBuilder();
director.Construct(buider1);
Hero dh = buider1.GetResult();

DHBuilder buider2 = new DHBuilder();
director.Construct(buider2);
Hero pom = buider1.GetResult();

2 總結

建造者模式具有一下優點

1、鬆散耦合

建造者模式把產品的構建過程獨立出來,實現產品構建和產品表現的分離,從而使得構建演算法可以復用,同時具體產品表現也可以靈活的擴展和切換。

2、可以很容易改變產品內部表示

在建造者模式中,Builder只提供介面給Director使用,具體的部件創建和裝配方式有具體的創建者實現類實現,Director不關註具體實現細節,這樣一來,如果像改變產品內部的表示,只需要修改具體建造者實現類即可。

3、更好的復用性

固定建造過程可以復用


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

-Advertisement-
Play Games
更多相關文章
  • HttpServletRequest: 表示瀏覽器向伺服器發送的請求報文,由Tomcat創建然後作為參數傳遞給我們doget,dopost方法。 功能:getParameter()獲取請求參數 getContextPath()獲取當前項目名 request..getRequestDispatcher ...
  • socketserver分類: 1、TCP協議 class socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True) 2、UDP協議 class socketserver.UDPServer(s ...
  • TensorFlow目錄結構。 ACKNOWLEDGMENTS #TensorFlow版本聲明 ADOPTERS.md #使用TensorFlow的人員或組織列表 AUTHORS #TensorFlow作者的官方列表 BUILD CONTRIBUTING.md #TensorFlow貢獻指導 ISS ...
  • 問題描述:爬取拉勾網python、工作地在北京的相關職業(python,北京),將結果保存。 1.頁面分析: 因為拉勾網有反爬蟲機制,所以需要設置相應的請求信息,由於職位信息AJAX非同步響應在頁面,所以直接訪問非同步請求。 查看響應: 2.代碼: 3.運行結果: 將結果以json格式保存到文件中: 格 ...
  • 如果有多個線程訪問共用資源,可能會出現當一個線程沒有處理完業務,然後另一個線程進入,從而導致共用資源出現不安全的情況。 日常例子:銀行取錢,A和B有擁有同一個銀行賬戶,A用存摺在櫃臺取錢,B在取款機取錢。取錢有兩個關鍵步驟: (1)判斷賬戶里的錢的餘額是否大於所取錢數 (2)如果大於所取錢數,則賬戶 ...
  • 前期準備: 申請微信支付後, 會收到2個參數, 商戶id,和商戶key.註意,這2個參數,不要和微信的參數混淆.微信參數: appid, appkey, token支付參數: merchant_id(商戶號), key(支付密鑰)支付密鑰怎麼得到?到 https://pay.weixin.qq.co ...
  • JavaSE組成部分:JDK、JRE、JVM、Java Java:Java語法 JDK:包含著JRE和一些常用的工具(JDK安裝目錄下的bin目錄下的可執行文件) JRE:包含著Java運行庫和JVM。 JVM:是運行所有Java位碼(.class)文件的操作系統,相當於虛擬機。Java所謂的"一次 ...
  • 反射空間編程 1.space(已創建的空間){ 1.描述{(描述應當是子集的一部分) //用於解析命令以及返回結果 描述是多種多樣的,它是一個(鍵-集合)關係的集合,比如{名字-{名稱1,別名1}} {語言-{En1,zh1……};動作-{手勢1,手勢2}} } 2.屬性{ //當多個space具有 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...