C#設計模式09——組合模式的寫法

来源:https://www.cnblogs.com/for-easy-fast/archive/2023/05/09/17386170.html
-Advertisement-
Play Games

1. 什麼是C#組合模式? 組合模式是一種結構型設計模式,它允許將對象組合成樹形結構以表示“整體/部分”層次結構。使用此模式,客戶端可以按相同的方式處理單個對象和對象集合,而不必關註它們是單個對象還是組合對象。組合對象本身也可以作為容器,包含其他組合對象,形成更複雜的樹形結構。 在C#中,組合模式是 ...


1. 什麼是C#組合模式?

組合模式是一種結構型設計模式,它允許將對象組合成樹形結構以表示“整體/部分”層次結構。使用此模式,客戶端可以按相同的方式處理單個對象和對象集合,而不必關註它們是單個對象還是組合對象。組合對象本身也可以作為容器,包含其他組合對象,形成更複雜的樹形結構。

在C#中,組合模式是一種遞歸嵌套的設計模式,通常需要使用抽象類或介面表示“整體”和“部分”之間的關係,並將部件對象存儲在它們的容器中。通過通過將容器中的部件繼續使用相同的方式處理,客戶端代碼可以逐級訪問嵌套對象,而不必知道每個對象的具體類型或是否是葉子節點。

2. 為什麼要使用C#組合模式?

組合模式可以方便地處理層次結構,例如組織機構、文件系統或UI控制項。使用該模式,可以將樹形數據結構的遍歷變得簡單且具有一致性,而無論遍歷哪個節點,只需按照相同的方式進行。

使用組合模式還可以使代碼更加靈活。由於容器和葉子節點可以互換使用,可以輕鬆地添加新的葉子節點和容器對象,而不會影響其它部分代碼的實現。

3. 組合模式的主要角色有哪些?

C#組合模式通常涉及四個主要角色:

- 抽象組件(Component): 定義組合關係的抽象類或介面,為容器和葉子節點共用的操作提供通用的實現。
- 葉子節點(Leaf): 組合樹結構中的最底層元素,它們沒有子節點,具有特定的行為。
- 容器(Composite): 包含一組子節點並維護它們之間的組合結構。容器可以包含其他容器和葉子節點,統一對子節點操作。
- 客戶端(Client): 使用組合結構的代碼,通常通過容器操作組合節點,而不必關註如何管理節點之間的組合關係,將複雜度降到最低。

4. 組合模式如何實現?

組合模式的一個常見實現方案是將組件抽象成介面或抽象類。這個抽象類包含容器和葉子節點的通用行為和屬性,並定義了添加、刪除和獲取子節點的方法。容器實現這個抽象類,並維護它們的子節點,而葉子節點擴展它們自己的邏輯。

通常情況下,容器會將它自己的操作通過遞歸調用委托給子節點,從而在深層次的嵌套結構中完成某個指定操作。客戶端代碼使用這個抽象介面或類,而不是具體的實現對象,實現了透明的管理樹形結構元素。

5. 組合模式有哪些優缺點?

優點:

- 可以方便地處理樹狀結構,具有一致性和可維護性。
- 組合對象可以遞歸嵌套,允許動態的添加和刪除節點和樹形結構。
- 通過共用相同介面或抽象類,客戶端代碼可以無縫切換一個元素與多個元素之間的關係,從而簡化代碼邏輯。
- 允許在葉子和組合對象中分別添加新的行為和操作,而不會影響其它部分的代碼。

缺點:

- 可能難以限制容器中的元素類型,會產生一定的安全隱患。
- 由於遞歸嵌套,可能對記憶體和性能有一定的影響。
- 當組合對象擁有大量子節點時,可能會對代碼可讀性和理解性造成一定的困難。

 

以下是一個使用C#組合模式的示例代碼:

//抽象組件
public abstract class Component
{
    protected string Name;
    public Component(string name)
    {
        Name = name;
    }
    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
}

//葉子節點
public class Leaf : Component
{
    public Leaf(string name) : base(name)
    {
    }
    public override void Add(Component c)
    {
        Console.WriteLine("Cannot add to a leaf");
    }
    public override void Remove(Component c)
    {
        Console.WriteLine("Cannot remove from a leaf");
    }
    public override void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + Name);
    }
}

//容器
public class Composite : Component
{
    private List<Component> _children = new List<Component>();
    public Composite(string name) : base(name)
    {
    }
    public override void Add(Component c)
    {
        _children.Add(c);
    }
    public override void Remove(Component c)
    {
        _children.Remove(c);
    }
    public override void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + Name);
        foreach (Component component in _children)
        {
            component.Display(depth + 2);
        }
    }
}

//客戶端
class Client
{
    static void Main(string[] args)
    {
        Composite root = new Composite("root");
        root.Add(new Leaf("Leaf A"));
        root.Add(new Composite("Composite X"));
        Composite compositeY = new Composite("Composite Y");
        compositeY.Add(new Leaf("Leaf B"));
        compositeY.Add(new Leaf("Leaf C"));
        root.Add(compositeY);
        Leaf leafD = new Leaf("Leaf D");
        root.Add(leafD);
        root.Remove(leafD);
        root.Display(1);

        Console.ReadKey();
    }
}

在上述代碼中,抽象組件是Component類,其中包含添加、刪除和展示子節點等公共方法。葉子節點Leaf和容器Composite分別繼承了Component,並實現了它們自己的邏輯。客戶端使用抽象組件Component來透明地處理葉子節點和容器對象,並對它們進行操作。在Main方法中,創建了一個根容器對象,並添加了一些葉子節點和容器對象。輸出結果是一個樹形結構。

-root
--Leaf A
--Composite X
--Composite Y
---Leaf B
---Leaf C

其中,輸出的內容是按照樹形結構展示的,每行前面添加了一些連字元("-")來表示層次結構深度。可以看到,root節點包含了三個子節點,其中compositeY節點又包含了兩個子節點。最後,“Leaf D”節點被移除了。

本文來自博客園,作者:明志德道,轉載請註明原文鏈接:https://www.cnblogs.com/for-easy-fast/p/17386170.html


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

-Advertisement-
Play Games
更多相關文章
  • 隨著之家3D虛擬化需求的增加,各產品線使用Unity引擎的項目也越來越多,新老項目共存,代碼維護成本也隨之增加。代碼質量參差加之代碼規範仍沒有完全統一產生高昂學習成本進一步加重了項目維護負擔。 為應對這些問題,我們決定藉助主機廠數科產品線銷冠神器VR版本大升級為契機,開發一套移動端通用Unity代碼... ...
  • 上一篇我介紹瞭如何在VSCode Webview中實現點擊鏈接下載圖片或文件,本文介紹如何在預設瀏覽器中打開一個新的頁面。 在瀏覽器中,如果要實現打開一個新的頁面有許多種不同的方法,例如: window.open("https://www.cnblogs.com/jaxu", "_blank"); ...
  • 大家好,我是DOM哥。 圖譜年年有,今年我來盤! 之前已經盤完了 Vue 的技術圖譜,今天來盤 React 的。不管你是資深 React 用戶,還是剛入門想學習 React 的小白,相信都能幫助到你 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 今天有一個需求,點擊選中某個英文單詞,然後對這個單詞做一些處理,例如高亮背景、查看一些詳細信息等等,今天簡單實現了一下,效果如下:(支持移動端,chrome和sarafi瀏覽器均能正常使用。語言🚀 vue3 + typescript) ...
  • 初識nodejs 19年年底一個偶然的機會接到年會任務,有微信掃碼登錄、投票、彈幕等功能,於是決定用node 來寫幾個服務,結果也比較順利。 當時用看了下koa2的官方文檔,知道怎麼連接資料庫、怎麼映射表實體,怎麼處理http,怎麼處理異常等,就可以直接寫起來了。從應用層面上來說 nodejs 入門 ...
  • jsonp 是前端一種用來解決網站跨域的技術,利用script標簽不受同源策略影響的特性引入一個非同源的js文件,並定義一個回調函數來接收數據,這樣就可以實現跨域獲取數據了,例如: 現在有一個鏈接返回的數據是這樣的: cb({ "name": "swk", "age": 18 }) 這是一個標準的j ...
  • JavaScript 中的記憶體泄漏是指程式中使用的記憶體不再被需要卻沒有被釋放,最終導致瀏覽器或者 Node.js 進程使用的記憶體越來越大,直到程式崩潰或者系統運行緩慢。 在 JavaScript 中,記憶體泄漏通常是由於變數、對象、閉包、事件監聽器等長期存在而沒有被釋放引起的。這些長期存在的引用會阻止 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 為了讓頁面保活更加穩定,你們是怎麼做的? 我用一行配置實現了 Vue頁面保活是指在用戶離開當前頁面後,可以在返回時恢覆上一次瀏覽頁面的狀態。這種技術可以讓用戶享受更加流暢自然的瀏覽體驗,而不會被繁瑣的操作打擾。 為什麼需要頁面保活? 頁面 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...