【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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...