【23種設計模式】建造者模式(四)

来源:https://www.cnblogs.com/wml-it/archive/2023/08/29/17665000.html
-Advertisement-
Play Games

## 前言 在軟體系統中,有時候面臨著“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的演算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中 ...


前言

在軟體系統中,有時候面臨著“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的演算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中的“穩定構建演算法”不隨著需求改變而改變?那就是今天分享的建造者模式,又叫生成器模式,英文名稱是Builder Pattern

建造者模式定義

在現實生活中,我們經常會遇到一些構成比較複雜的物品,比如:汽車、電腦和手機等等。它們是一個複雜的物品,主要是由各種零部件組裝而成的,他們的組裝過程是固定的。就拿汽車來說,組裝流水線是固定的,不變的,需要把底盤、車輪、車門、車燈、發動機引擎、車燈和排氣筒等等組裝在一起。但是由於需求的變化,這個汽車複雜對象針對不同的品牌,各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。建造者設計模式定義就是將一個複雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。

建造者模式組成

(1)抽象建造者角色(Builder):為創建一個Product對象的各個部件指定抽象介面,以規範產品對象的各個組成成分的建造。一般而言,此角色規定要實現複雜對象的哪些部分的創建,並不涉及具體的對象部件的創建。

(2)具體建造者(ConcreteBuilder)

  • 實現Builder的介面以構造和裝配該產品的各個部件。即實現抽象建造者角色Builder的方法。
  • 定義並明確它所創建的表示,即針對不同的商業邏輯,具體化複雜對象的各部分的創建。
  • 提供一個檢索產品的介面。
  • 構造一個使用Builder介面的對象即在指導者的調用下創建產品實例。

(3)指導者(Director):調用具體建造者角色以創建產品對象的各個部分。指導者並沒有涉及具體產品類的信息,真正擁有具體產品的信息是具體建造者對象。它只負責保證對象各部分完整創建或按某種順序創建。

(4)產品角色(Product):建造中的複雜對象,對應具體的產品。它要包含那些定義組件的類,包括將這些組件裝配成產品的介面。

image

建造者模式代碼實現

image

抽象建造者
 /// <summary>
    /// 抽象建造者,它定義了要創建什麼部件和最後創建的結果,但是不是組裝的的類型
    /// </summary>
    public abstract class Builder
    {
        /// <summary>
        /// 創建車門
        /// </summary>
        public abstract void BuildCarDoor();
        /// <summary>
        /// 創建車輪
        /// </summary>
        public abstract void BuildCarWheel();
        /// <summary>
        /// 創建車引擎
        /// </summary>
        public abstract void BuildCarEngine();


        /*
         * 當然還有部件:
         * 大燈
         * 地盤
         * ....
         * ....
         */

        /// <summary>
        /// 獲得組裝完成的汽車
        /// </summary>
        /// <returns></returns>
        public abstract Car GetCar();
    }
具體建造者

別克:

 /// <summary>
    /// 具體建造者,具體的車型的建造者,例如:別克
    /// </summary>
    public sealed class BuickBuilder : Builder
    {
        Car buickCar = new Car("別克");
        public override void BuildCarDoor()
        {
            buickCar.Add("Buick's Door");
        }

        public override void BuildCarWheel()
        {
            buickCar.Add("Buick's Wheel");
        }

        public override void BuildCarEngine()
        {
            buickCar.Add("Buick's Engine");
        }

        public override Car GetCar()
        {
            return buickCar;
        }
    }

奧迪:

/// <summary>
    /// 具體建造者,具體的車型的建造者,例如:奧迪
    /// </summary>
    public sealed class AoDiBuilder : Builder
    {
        Car aoDiCar = new Car("奧迪");
        public override void BuildCarDoor()
        {
            aoDiCar.Add("Aodi's Door");
        }

        public override void BuildCarWheel()
        {
            aoDiCar.Add("Aodi's Wheel");
        }

        public override void BuildCarEngine()
        {
            aoDiCar.Add("Aodi's Engine");
        }

        public override Car GetCar()
        {
            return aoDiCar;
        }
    }
汽車固定組裝流程定義
 /// <summary>
    /// 汽車類
    /// </summary>
    public sealed class Car
    {
        // 汽車部件集合
        private IList<string> parts = new List<string>();
        //汽車品牌名
        private string _brandName;
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="brandName"></param>
        public Car(string brandName)
        {
            _brandName = brandName;
        }
        /// <summary>
        /// 把單個部件添加到汽車部件集合中
        /// </summary>
        /// <param name="part"></param>
        public void Add(string part)
        {
            parts.Add(part);
        }
        /// <summary>
        /// 汽車組裝流程
        /// </summary>
        public void Assembly()
        {
            Console.WriteLine($"{_brandName}汽車開始在組裝.......");
            foreach (string part in parts)
            {
                Console.WriteLine("組件" + part + "已裝好...");
            }

            Console.WriteLine($"{_brandName}汽車組裝完畢.........");
        }
    }
指導者

這裡才是調用組裝的,Construct方法裡面的實現就是創建複雜對象固定演算法的實現,根據具體需求變化,控制組裝的流程順序,該演算法是固定的,或者說是相對穩定的。

 /// <summary>
    /// 自動化工廠操控台,也就是建造者模式中的指揮者
    /// </summary>
    public class Director
    {
        /// <summary>
        /// 自動化演算法指導組裝汽車
        /// </summary>
        /// <param name="builder"></param>
        public void Construct(Builder builder)
        {
            builder.BuildCarDoor();
            builder.BuildCarWheel();
            builder.BuildCarEngine();
            /*
             * 指導其他流程
             */
        }
    }
調用
  /// <summary>
        /// 測試方法
        /// </summary>
        public void RunTest()
        {
            Director director = new Director();

            //組裝別克
            Builder buickCarBuilder = new BuickBuilder();
            director.Construct(buickCarBuilder);
            Car buickCar = buickCarBuilder.GetCar();
            buickCar.Assembly();

            Console.WriteLine("\r\n*****************************\r\n");

            //組裝奧迪
            Builder aoDiCarBuilder = new AoDiBuilder();
            director.Construct(aoDiCarBuilder);
            Car aoDiCar = aoDiCarBuilder.GetCar();
            aoDiCar.Assembly();
        }

image

建造者模式優缺點

優點:

  • 使用建造者模式可以使客戶端不必知道產品內部組成的細節

  • 具體的建造者類之間是相互獨立的,容易擴展

  • 由於具體的建造者是獨立的,因此可以對建造過程逐步細化,而不對其他的模塊產生任何影響。

缺點:

  • 產生多餘的Build對象以及Director類。

本文來自博客園,作者:碼農阿亮,轉載請註明原文鏈接:https://www.cnblogs.com/wml-it/p/17665000.html


技術的發展日新月異,隨著時間推移,無法保證本博客所有內容的正確性。如有誤導,請大家見諒,歡迎評論區指正!
開源庫地址,歡迎點亮:
GitHub:https://github.com/ITMingliang
Gitee:   https://gitee.com/mingliang_it
GitLab: https://gitlab.com/ITMingliang

建群聲明: 本著技術在於分享,方便大家交流學習的初心,特此建立【編程內功修煉交流群】,為大家答疑解惑。熱烈歡迎各位愛交流學習的程式員進群,也希望進群的大佬能不吝分享自己遇到的技術問題和學習心得!進群方式:掃碼關註公眾號,後臺回覆【進群】。



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

-Advertisement-
Play Games
更多相關文章
  • ## 指令重排序 ### 1、問題描述 首先一定要明確:指令重排序和有序性是不一樣的。這一點非常重要。 我們經常都會這麼說: - volatile能保證記憶體可見性、禁止指令重排序但是不能保證原子性。 - synchronized能保證原子性、可見性和有序性。 > 註意:這裡的有序性並不是代表能禁止指 ...
  • 本文分享自華為雲社區《哪些場景下Spring的事務會失效?》,作者:冰 河 。 在日常工作中,如果對Spring的事務管理功能使用不當,則會造成Spring事務不生效的問題。而針對Spring事務不生效的問題,也是在跳槽面試中被問的比較頻繁的一個問題。 今天,我們就一起梳理下有哪些場景會導致Spri ...
  • ### 前言 AC自動機($Aho\ Corasick\ Atomaton$)有著一種 [$KMP$](https://www.cnblogs.com/pdpdzaa/p/17641166.html) 的思想,所以在學習之前建議先學一下 $KMP$。同時還需要瞭解一下 $Trie$ 樹(建議去看一下 ...
  • `go embed` 是 Go 1.16 中引入的特性,它允許將文件嵌入到 Go 代碼中,以便在運行時訪問這些文件。這對於將靜態資源(如 HTML、CSS、JavaScript 文件)直接嵌入到 Go 二進位文件中,以及簡化文件分發和部署非常有用。下麵是關於 `go embed` 的詳細介紹: ** ...
  • ## 教程簡介 R是用於統計分析、繪圖的語言和操作環境。R是屬於GNU系統的一個自由、免費、源代碼開放的軟體,它是一個用於統計計算和統計製圖的優秀工具。R語言的核心是解釋電腦語言,其允許分支和迴圈以及使用函數的模塊化編程。 R語言允許與以C,C ++,.Net,Python或FORTRAN語言編寫 ...
  • 作者:TinyThing 鏈接:https://www.jianshu.com/p/b52db905f020 ## 0x0 背景 > 項目中使用LocalDateTime系列作為dto中時間的類型,但是spring收到參數後總報錯,為了全局配置時間類型轉換,嘗試瞭如下3中方法。 > > **註:本文 ...
  • ### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 本篇概覽 - 本篇是《java與es8實戰》系列的第四 ...
  • 昨天分享了一個在WebApi中如何接收參數的文章 傳送門,然後有新人小伙伴就問了,那文件上傳呢,這個怎麼弄,藉此我寫了一個小demo,分享給大家。 通常來說,上傳文件,我們是使用POST,還是老規矩先上代碼: txt文件 這是需要上傳的txt文件。 指定文件參數名 代碼 [HttpPost("Upl ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...