【23種設計模式】組合模式(八)

来源:https://www.cnblogs.com/wml-it/archive/2023/09/11/17693267.html
-Advertisement-
Play Games

前言 組合模式,英文名稱是:Composite Pattern。當我們談到這個模式的時候,有一個物件和這個模式很像,也符合這個模式要表達的意思,那就是“俄羅斯套娃”。“俄羅斯套娃”就是大的瓷器娃娃裡面裝著一個小的瓷器娃娃,小的瓷器娃娃裡面再裝著更小的瓷器娃娃,直到最後一個不能再裝更小的瓷器娃娃的那個 ...


前言

組合模式,英文名稱是:Composite Pattern。當我們談到這個模式的時候,有一個物件和這個模式很像,也符合這個模式要表達的意思,那就是“俄羅斯套娃”。“俄羅斯套娃”就是大的瓷器娃娃裡面裝著一個小的瓷器娃娃,小的瓷器娃娃裡面再裝著更小的瓷器娃娃,直到最後一個不能再裝更小的瓷器娃娃的那個瓷器娃娃為止。在我們的操作系統中有文件夾的概念,文件夾可以包含文件夾,可以嵌套多層,最裡面包含的是文件,這個概念和“俄羅斯套娃”很像。
image

組合模式的定義

客戶代碼過多地依賴於對象容器複雜的內部實現結構,對象容器內部實現結構的變化將引起客戶代碼的頻繁變化,帶來了代碼的維護性、擴展性等方面的弊端。組合設計模式就是將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。

組合模式的組成

image

  • 抽象構件角色(Component):這是個抽象角色,它給參加組合的對象定義出了公共的介面及預設行為,可以用來管理所有的子對象。在安全式的組合模式里,構件角色並不定義出管理子對象的方法,這一定義由樹枝結構對象給出。

  • 樹葉構件角色(Leaf):樹葉對象是沒有下級子對象的對象,定義出參加組合的原始對象的行為。(原始對象的行為可以理解為沒有容器對象管理子對象的方法,或者 【原始對象行為】+【管理子對象的行為(Add,Remove等)】=面對客戶代碼的介面行為集合)

  • 樹枝構件角色(Composite):代表參加組合的有下級子對象的對象,樹枝對象給出所有管理子對象的方法實現,如Add、Remove等。

組合模式的代碼實現

組合模式有兩種實現方式,一種是:透明式的組合模式,另外一種是:安全式的組合模式。

所謂透明式是指“抽象構件角色”定義的介面行為集合包含兩個部分,一部分是葉子對象本身所包含的行為(比如Operation),另外一部分是容器對象本身所包含的管理子對象的行為(Add,Remove)。這個抽象構件必須同時包含這兩類對象所有的行為,客戶端代碼才會透明的使用,無論調用容器對象還是葉子對象,介面方法都是一樣的,這就是透明

所謂安全式是指“抽象構件角色”只定義葉子對象的方法,確切的說這個抽象構件只定義兩類對象共有的行為,然後容器對象的方法定義在“樹枝構件角色”上,這樣葉子對象有葉子對象的方法,容器對象有容器對象的方法,這樣責任很明確,當然調用肯定不會拋出異常了。

大家可以根據自己的情況自行選擇是實現為“透明式”還是“安全式”的,以下我們會針對這兩種情況都有實現,具體實現如下:

透明式

代碼定義

 /// <summary>
    /// Transparent 透明式實現
    /// </summary>
    public class Transparent
    {
        /// <summary>
        /// 該抽象類就是文件夾抽象介面的定義,該類型就相當於是抽象構件Component類型
        /// </summary>
        public abstract class Folder
        {
            //增加文件夾或文件
            public abstract void Add(Folder folder);

            //刪除文件夾或者文件
            public abstract void Remove(Folder folder);

            //打開文件或者文件夾--該操作相當於Component類型的Operation方法
            public abstract void Open();
        }

        /// <summary>
        /// 該Word文檔類就是葉子構件的定義,該類型就相當於是Leaf類型,不能在包含子對象
        /// </summary>
        public sealed class Word : Folder
        {
            //增加文件夾或文件
            public override void Add(Folder folder)
            {
                throw new Exception("Word文檔不具有該功能");
            }

            //刪除文件夾或者文件
            public override void Remove(Folder folder)
            {
                throw new Exception("Word文檔不具有該功能");
            }

            //打開文件--該操作相當於Component類型的Operation方法
            public override void Open()
            {
                Console.WriteLine("打開Word文檔,開始進行編輯");
            }
        }

        /// <summary>
        /// SonFolder類型就是樹枝構件,由於我們使用的是“透明式”,所以Add,Remove都是從Folder類型繼承下來的
        /// </summary>
        public class SonFolder : Folder
        {
            //增加文件夾或文件
            public override void Add(Folder folder)
            {
                Console.WriteLine("文件或者文件夾已經增加成功");
            }

            //刪除文件夾或者文件
            public override void Remove(Folder folder)
            {
                Console.WriteLine("文件或者文件夾已經刪除成功");
            }

            //打開文件夾--該操作相當於Component類型的Operation方法
            public override void Open()
            {
                Console.WriteLine("已經打開當前文件夾");
            }
        }
    }

調用實現

  public void RunTest()
        {
            //Folder myword = new Word();
            //myword.Open();//打開文件,處理文件

            //myword.Add(new SonFolder());//拋出異常
            //myword.Remove(new SonFolder());//拋出異常


            Folder myfolder = new SonFolder();
            myfolder.Open();//打開文件夾

            myfolder.Add(new SonFolder());//成功增加文件或者文件夾
            myfolder.Remove(new SonFolder());//成功刪除文件或者文件夾

            Console.Read();
        }

image

安全式

代碼定義

  /// <summary>
    /// Secure 安全式實現
    /// </summary>
    public class Secure
    {
        /// <summary>
        /// 該抽象類就是文件夾抽象介面的定義,該類型就相當於是抽象構件Component類型
        /// </summary>
        public abstract class Folder //該類型少了容器對象管理子對象的方法的定義,換了地方,在樹枝構件也就是SonFolder類型
        {
            //打開文件或者文件夾--該操作相當於Component類型的Operation方法
            public abstract void Open();
        }

        /// <summary>
        /// 該Word文檔類就是葉子構件的定義,該類型就相當於是Leaf類型,不能在包含子對象
        /// </summary>
        public sealed class Word : Folder  //這類型現在很乾凈
        {
            //打開文件---該操作相當於Component類型的Operation方法
            public override void Open()
            {
                Console.WriteLine("打開Word文檔,開始進行編輯");
            }
        }

        /// <summary>
        /// SonFolder類型就是樹枝構件,現在由於我們使用的是“安全式”,所以Add,Remove都是從此處開始定義的
        /// </summary>
        public abstract class SonFolder : Folder //這裡可以是抽象介面,可以自己根據自己的情況而定
        {
            //增加文件夾或文件
            public abstract void Add(Folder folder);

            //刪除文件夾或者文件
            public abstract void Remove(Folder folder);

            //打開文件夾--該操作相當於Component類型的Operation方法
            public override void Open()
            {
                Console.WriteLine("已經打開當前文件夾");
            }
        }

        /// <summary>
        /// NextFolder類型就是樹枝構件的實現類
        /// </summary>
        public sealed class NextFolder : SonFolder
        {
            //增加文件夾或文件
            public override void Add(Folder folder)
            {
                Console.WriteLine("文件或者文件夾已經增加成功");
            }

            //刪除文件夾或者文件
            public override void Remove(Folder folder)
            {
                Console.WriteLine("文件或者文件夾已經刪除成功");
            }

            //打開文件夾--該操作相當於Component類型的Operation方法
            public override void Open()
            {
                Console.WriteLine("已經打開當前文件夾");
            }
        }

    }

調用實現

  public void RunTest()
        {
            //這是安全的組合模式
            Folder myword = new Word();

            myword.Open();//打開文件,處理文件


            Folder myfolder = new NextFolder();
            myfolder.Open();//打開文件夾

            //此處要是用增加和刪除功能,需要轉型的操作,否則不能使用
            ((SonFolder)myfolder).Add(new NextFolder());//成功增加文件或者文件夾
            ((SonFolder)myfolder).Remove(new NextFolder());//成功刪除文件或者文件夾

        }

image

組合模式的優缺點

優點
  • 組合模式使得客戶端代碼可以一致地處理對象和對象容器,無需關心處理的是單個對象,還是組合的對象容器。

  • 將”客戶代碼與複雜的對象容器結構“解耦。

  • 可以更容易地往組合對象中加入新的構件。

缺點
  • 使得設計更加複雜。客戶端需要花更多時間理清類之間的層次關係。

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


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

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



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

-Advertisement-
Play Games
更多相關文章
  • 日誌是應用程式的重要組成部分。無論是服務端程式還是客戶端程式都需要日誌做為錯誤輸出或者業務記錄。在這篇文章中,我們結合log4rs聊聊rust 程式中如何使用日誌。 ...
  • 本章筆者將介紹一種通過Metasploit生成ShellCode並將其註入到特定PE文件內的Shell植入技術。該技術能夠劫持原始PE文件的入口地址,在PE程式運行之前執行ShellCode反彈,執行後掛入後臺並繼續運行原始程式,實現了一種隱蔽的Shell訪問。而我把這種技術叫做位元組註入反彈。位元組註... ...
  • 1.網關介紹 如果沒有網關,難道不行嗎?功能上是可以的,我們直接調用提供的介面就可以了。那為什麼還需要網關? 因為網關的作用不僅僅是轉發請求而已。我們可以試想一下,如果需要做一個請求認證功能,我們可以接入到 API 服務中。但是倘若後續又有服務需要接入,我們又需要重覆接入。這樣我們不僅代碼要重覆編寫 ...
  • 開心一刻 昨晚和一個朋友聊天 我:處對象嗎,咱倆試試? 朋友:我有對象 我:我不信,有對象不公開? 朋友:不好公開,我當的小三 問題背景 程式在生產環境穩定的跑著 直到有一天,公司執行組件漏洞掃描,有漏洞的 jar 要進行升級修複 然後我就按著掃描報告將有漏洞的 jar 修複到指定的版本 自己在開發 ...
  • Unity 性能優化Shader分析處理函數:ShaderUtil.GetShaderGlobalKeywords用法 點擊封面跳轉下載頁面 簡介 Unity 性能優化Shader分析處理函數:ShaderUtil.GetShaderGlobalKeywords用法 在Unity開發中,性能優化是一 ...
  • try catch使用場景: 1. 一般線上程,委托中使用, 線上程與委托中使用是因為,如果線程和委托中出現異常在程式外部是捕獲不到的,需要在內部做單獨處理。 2. 程式的外層使用,比如程式的入口處加一個全局異常捕獲,這樣整個程式發生的異常都可以捕獲到。 3. 在事件或者主體方法中使用,一些小的公共 ...
  • 1. 什麼是IDisposable? IDisposable介面是一個用於約定可進行釋放資源操作的介面,一個類實現該介面則意味著可以使用介面約定的方法Dispose來釋放資源。其定義如下: public interface IDisposable { void Dispose(); } 上述描述中可 ...
  • 針對工業來講,特殊是流程行業,視圖建模(Web組態)是必不可少應用場景,因為有很多工序要直觀的展示工藝流程圖。該功能也廣泛應用在:鋼鐵、煤炭、水務、中醫葯、能源、航天、加工製造、風電、儲能等領域。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...