首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 設計模式實戰:組合模式完整解析與公司組織結構案例

     編輯:關於.NET

一、組合模式簡介

定義: 將物件組合成樹狀結構以表示「部分-整體」的層次關係,使客戶端對單一物件與組合物件的使用具有一致性。

核心解決問題: 讓「整體」與「部分」能被一致對待,消除客戶端區分葉節點與分支節點的邏輯判斷。

二、組合模式結構分析

組合模式 UML 結構圖

核心角色

  • Component (抽象元件):宣告介面,定義存取與管理子元件的方法(Add、Remove)、顯示方法(Display)。
  • Leaf (葉節點):無子節點,Add/Remove 無實際意義(或拋出例外/輸出提示),僅實作 Display。
  • Composite (分支節點):擁有子元件集合,實作 Add、Remove、Display(遞迴呼叫子元件 Display)。

三、基礎結構程式碼實作 (C#)

1. 抽象類別 Component

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);
}

2. 葉節點 Leaf

public class Leaf : Component
{
    public Leaf(string name) : base(name) { }

    public override void Add(Component c)
    {
        Console.WriteLine("不能向葉子節點添加子節點");
    }

    public override void Remove(Component c)
    {
        Console.WriteLine("葉子節點沒有子節點");
    }

    public override void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + _name);
    }
}

3. 分支節點 Composite

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);
        }
    }
}

4. 用戶端測試程式碼

static void Main(string[] args)
{
    Composite root = new Composite("根節點root");
    root.Add(new Leaf("根上生出的葉子A"));
    root.Add(new Leaf("根上生出的葉子B"));

    Composite comp = new Composite("根上生出的分支CompositeX");
    comp.Add(new Leaf("分支CompositeX生出的葉子LeafXA"));
    comp.Add(new Leaf("分支CompositeX生出的葉子LeafXB"));

    root.Add(comp);

    Composite comp2 = new Composite("分支CompositeX生出的分支CompositeXY");
    comp2.Add(new Leaf("分支CompositeXY生出葉子LeafXYA"));
    comp2.Add(new Leaf("分支CompositeXY生出葉子LeafXYB"));

    comp.Add(comp2);

    root.Add(new Leaf("根節點生成的葉子LeafC"));
    Leaf leafD = new Leaf("leaf D");
    root.Add(leafD);
    root.Remove(leafD);

    root.Display(1);
    Console.Read();
}

5. 程式執行結果

樹狀結構輸出結果

四、實務案例:公司組織結構薪資計算

場景描述

公司組織架構如下:

總經理
├─ 技術部經理
│  ├─ 開發人員A
│  └─ 開發人員B
└─ 銷售部經理 (暫無下屬,未來可擴充)

公司組織結構圖

需求:計算整個組織的總薪資,以及各部門層級的薪資總和。

介面與類別設計

// 1. 共同介面
public interface IComponent
{
    string Title { get; set; }
    decimal Salary { get; set; }
    void Add(IComponent c);
    void GetCost(ref decimal salary);
}

// 2. 葉節點:一般員工
public class Component : IComponent
{
    public string Title { get; set; }
    public decimal Salary { get; set; }

    public Component(string title, decimal salary)
    {
        Title = title;
        Salary = salary;
    }

    public void Add(IComponent c)
    {
        Console.WriteLine("Cannot add to the leaf!");
    }

    public void GetCost(ref decimal salary)
    {
        salary += Salary;
    }
}

// 3. 分支節點:管理職
public class Composite : IComponent
{
    private List<IComponent> _listEmployees = new List<IComponent>();
    public string Title { get; set; }
    public decimal Salary { get; set; }

    public Composite(string title, decimal salary)
    {
        Title = title;
        Salary = salary;
    }

    public void Add(IComponent comp)
    {
        _listEmployees.Add(comp);
    }

    public void GetCost(ref decimal salary)
    {
        salary += this.Salary;
        foreach (IComponent component in _listEmployees)
        {
            component.GetCost(ref salary);
        }
    }
}

用戶端程式碼

static void Main(string[] args)
{
    decimal costCEO = 0.0M;
    decimal costVPD = 0.0M;

    // 建立 CEO 節點
    IComponent compCEO = new Composite("CEO", 500000);

    // 建立 VP-Development 及開發人員
    IComponent compVPDev = new Composite("VP-Development", 250000);
    IComponent compDev1 = new Component("Developer1", 75000);
    IComponent compDev2 = new Component("Developer2", 50000);
    compVPDev.Add(compDev1);
    compVPDev.Add(compDev2);

    // 建立 VP-Sales (暫無下屬,但用 Composite 以利未來擴充)
    IComponent compVPSales = new Composite("VP-Sales", 300000);

    compCEO.Add(compVPDev);
    compCEO.Add(compVPSales);

    // 計算 CEO 層級總薪資 (含所有下屬)
    compCEO.GetCost(ref costCEO);
    Console.WriteLine(String.Format("The Cost incurred at the CEO level is {0:c} ", costCEO));

    // 計算 VP-Development 層級總薪資
    compVPDev.GetCost(ref costVPD);
    Console.WriteLine(String.Format("The Cost incurred at the VP-Development level is {0:c} ", costVPD));
}

五、總結

組合模式以樹狀結構優雅解決「部分-整體」一致性問題。無論是簡單的圖形繪製、檔案系統目錄、UI 控制項樹,還是複雜的組織架構、薪資計算、選單系統,皆為其經典應用場景。關鍵在於統一介面讓客戶端無需區分葉節點與分支節點,透過遞迴實現整體操作。

出處:https://www.cnblogs.com/ywqu

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved