C#設計模式之組合模式

提高班14期郭倩_Ulrica發表於2018-06-05

前言

拿大米時代來考慮這個問題是最合適不過的。將大米時代看作總公司,其他分校看成分公司,各個分公司都有自己的很多部門。。。

組合模式

英文:Composite

what

將物件組合成樹形結構以表示“部分-整體”的層次結構。組合模式使得使用者對單個物件和組合物件的使用具有一致性。

結構圖

組合

場景

拿我們們處在的大米時代舉例子。大米時代有計算機和英語,計算機又分為學術部門,紀律部門,安全部門等,這就可以使用組合模式。

  1. 公司類(抽象類,或介面)
  2. 具體公司類(大米時代→實現介面,樹枝節點)
  3. 各個部門類(樹葉節點)

應用

當你發現需求中是體現部分與整體層次的結構時,以及你希望使用者可以忽略組合物件與單個物件的不同,統一使用組合結構中的所有物件時,就應該考慮用組合模式。

好處

定義了包含基本物件和分公司等組合物件的類層次結構。基本物件可以被組合成更復雜的組合物件,而這個組合物件又可以被組合,這樣不斷的遞迴下去,客戶程式碼中,任何用到基本物件的地方都可以使用組合物件了。
組合模式可以讓客戶可以一致的使用組合結構和單個物件。(也就是說,一個公司設多少個分公司都沒問題)

錯誤解決

1 不實現繼承的抽象成員remove

錯誤

2 解決:

首先,這裡提到了remove,所以檢查方法有沒有錯誤
沒有錯誤之後看一下是否繼承了方法。看了程式碼之後清楚了原來是繼承了其他三個,由於粗心,將remove遺漏了,所以新增上程式碼:

public override void Remove(Company hengshui)
        {
            children.Remove(hengshui);
        }

3 分支不顯示:

分支

4 解決

錯誤程式碼:

comp.Add(comp);//將分支誤寫成了定義的分校變數

正確程式碼:

root.Add(comp);  //分支

程式碼展示

抽象公司類:(抽象類或介面)

//抽象公司類
    abstract class Company
    {
        protected string name;

        public Company(string name)
        {
            this.name = name;
        }

        public abstract void Add(Company c);//增加
        public abstract void Remove(Company c);//移除
        public abstract void Display(int depth);//顯示
        public abstract void LineOfDuty();//履行職責,這個方法使得不同部門履行不同職責

    }

具體公司類:(樹枝節點)

class ConcreteCompany:Company
    {
        private List<Company> children = new List<Company>();

        public ConcreteCompany(string name)
            : base(name)
        { }

        //增加
        public override void Add(Company c)
        {
            children.Add(c);
        }

        public override void Remove(Company c)
        {
            children.Remove(c);
        }

        //重寫顯示
        public override void Display(int depth)
        {
            Console.WriteLine(new string ('-',depth)+name);

            foreach (Company component in children)
            {
                component.Display(depth + 1);
            }
        }

        //重寫履行職責
        public override void LineOfDuty()
        {
            foreach (Company component in children)
            {
                component.LineOfDuty();
            }
        }
    }

部門類(樹葉節點)

//具體人力資源部門
    class HRDepartment:Company 
    {
        public HRDepartment(string name)
            : base(name)
        { }

        public override void Add(Company c)
        { }

        public override void Remove(Company c)
        { }

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

        public override void LineOfDuty()
        {
            Console.WriteLine("{0}員工招聘培訓管理",name);
        }
    }

//財務部,程式碼同上↑
    class FinanceDepartment : Company
    {
        //程式碼同上HR
    }

客戶端程式碼:

static void Main(string[] args)
        {
        //總
            ConcreteCompany root = new ConcreteCompany("大米時代總公司");
            root.Add(new HRDepartment("人力資源部門"));
            root.Add(new FinanceDepartment("財務部門"));

        //分----可層次增加分公司
            ConcreteCompany comp = new ConcreteCompany("衡水分校");
            comp.Add(new HRDepartment("衡水分校人力資源部門"));
            comp.Add(new FinanceDepartment("衡水分校財務部門"));
            root.Add(comp);
        //分
            ConcreteCompany comp1 = new ConcreteCompany("石家莊分校");
            comp1.Add(new HRDepartment("石家莊分校人力資源部門"));
            comp1.Add(new FinanceDepartment("石家莊分校財務部門"));
            root.Add(comp1);

        //顯示結構圖
            Console.WriteLine("\n結構圖:");
            root.Display(1);

        //履行職責
            Console.WriteLine("\n職責");
            root.LineOfDuty();

            Console.Read();
        }
    }

最後效果圖示:

組合

後記

也在這裡預祝大米時代能夠帶更多的人走向一個全新的教育模式~

相關文章