亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#中的composite模式示例詳解

 更新時(shí)間:2022年06月20日 08:22:40   作者:老胡寫代碼  
Composite組合模式屬于設(shè)計(jì)模式中比較熱門的一個(gè),相信大家對它一定不像對訪問者模式那么陌生,這篇文章主要介紹了C#中的composite模式,需要的朋友可以參考下

寫在前面

Composite組合模式屬于設(shè)計(jì)模式中比較熱門的一個(gè),相信大家對它一定不像對訪問者模式那么陌生,畢竟誰又沒有遇到過樹形結(jié)構(gòu)呢。不過所謂溫故而知新,我們還是從一個(gè)例子出發(fā),起底一下這個(gè)模式吧。

一個(gè)簡單例子

設(shè)想我們要建立一個(gè)公司的人事架構(gòu),在一個(gè)公司里,我們可以簡單地分為兩種員工,一種是經(jīng)理(包括老板),另一種是基層員工,經(jīng)理可以有下屬,而普通員工不行,我們寫出這樣的代碼。

基層員工類

這種員工是最基層的員工,沒有下屬

class BasicLevelEmployee //基層員工
{
    public string ID { get; set; }
    public void ShowStatus(int indent)
    {
        string str = ID;
        str = str.PadLeft(ID.Length + indent, '-');
        Console.WriteLine(str);
    }
}

經(jīng)理類

經(jīng)理可以有下屬,下屬可能是基層員工,也可能是其他經(jīng)理(考慮老板這種情況,無疑其他經(jīng)理也是老板的下屬),因?yàn)楸然鶎訂T工多了下屬,所以也多了一些方法維護(hù)下屬屬性

class Manager //經(jīng)理
{
    public string ID { get; set; }
    public void ShowStatus(int indent) 
    {
        string str = ID;            
        str = str.PadLeft(ID.Length + indent, '-');
        Console.WriteLine(str);
        indent += 4;
        Subordinate.ForEach(s => s.ShowStatus(indent));
        SubordinateManagers.ForEach(m => m.ShowStatus(indent));
    }
    public List<BasicLevelEmployee> Subordinate = new List<BasicLevelEmployee>();
    public List<Manager> SubordinateManagers = new List<Manager>();
    //下面是經(jīng)理所屬的方法
    public void AddSubordinate(BasicLevelEmployee e) { Subordinate.Add(e); }
    public void AddSubordinate(Manager e) { SubordinateManagers.Add(e); }
    public void RemoveSubordinate(BasicLevelEmployee e) { Subordinate.Remove(e); }
    public void RemoveSubordinate(Manager e) { SubordinateManagers.Remove(e); }      
}

公司架構(gòu)類

公司架構(gòu)類非常簡單,只需要掌握最大的BOSS,整個(gè)公司人事架構(gòu)都可以順藤摸瓜的展示出來

class CompanyHierachy
{
    public Manager BOSS { get; set; }
    public void ShowStatus()
    {
        BOSS.ShowStatus(0);
    }
}

客戶端代碼

假設(shè)這個(gè)公司的結(jié)構(gòu)很單純,除了老板就是開發(fā)部門和財(cái)務(wù)部門,各個(gè)部門分設(shè)經(jīng)理是,所以我們寫出代碼如下

class Program
{
    static void Main(string[] args)
    {
        //老板
        Manager boss = new Manager() { ID = "BOSS" };
        //開發(fā)部門經(jīng)理
        Manager devManager = new Manager() { ID = "Dev Manager" };
        //財(cái)務(wù)部門經(jīng)理
        Manager financeManager = new Manager() { ID = "Finance Manager" };
        //開發(fā)組長
        Manager devLead = new Manager() { ID = "Dev Lead" };
        //測試組長
        Manager qcLead = new Manager() { ID = "QC Lead" };

        boss.AddSubordinate(devManager);
        boss.AddSubordinate(financeManager);
        financeManager.AddSubordinate(new BasicLevelEmployee() { ID = "Purchase" });
        devManager.AddSubordinate(devLead);
        devManager.AddSubordinate(qcLead);
        devLead.AddSubordinate(new BasicLevelEmployee() { ID = "Developer1" });
        devLead.AddSubordinate(new BasicLevelEmployee() { ID = "Developer2" });
        qcLead.AddSubordinate(new BasicLevelEmployee() { ID = "QuanityControl1" });
        qcLead.AddSubordinate(new BasicLevelEmployee() { ID = "QuanityControl2" });
        CompanyHierachy company = new CompanyHierachy() { CEO = boss };
        company.ShowStatus();
    }
}

代碼非常簡單,不需要更多解釋了,運(yùn)行后得到結(jié)果

一切正常,代碼是工作的,公司架構(gòu)建立成功了。

再想一下

但是想想,這樣的代碼真的好嗎?感覺起碼有兩個(gè)地方我們可以改進(jìn)。

  • 基層員工和經(jīng)理其實(shí)有太多的共性(屬性和方法),可以利用抽象思維,讓他們繼承自同一種東西嗎?
  • 在經(jīng)理類中我們維護(hù)了多個(gè)下屬列表,如果以后再加一個(gè)實(shí)習(xí)生,是不是我們又得創(chuàng)建更多的列表?如果我們使用了繼承,這個(gè)問題還會(huì)存在嗎?

基于此,利用抽象思維讓經(jīng)理和員工繼承自同一個(gè)類(雇員)勢在必行。在抽象之后,經(jīng)理類會(huì)繼承自雇員并且也內(nèi)含雇員列表,可能第一次見到這種包含自身父類列表的設(shè)計(jì)方式會(huì)讓人感覺不習(xí)慣,但不用擔(dān)心,這其實(shí)是一種比較常見的設(shè)計(jì)方式。這種既有繼承也有合成的結(jié)構(gòu),就是組合模式的精髓。

使用組合模式進(jìn)行重構(gòu)

組合模式屬于結(jié)構(gòu)型設(shè)計(jì)模式,它利用類型層級和聚合層級構(gòu)造更大的復(fù)合結(jié)構(gòu)

說的更加直白一點(diǎn),當(dāng)對象的局部結(jié)構(gòu)和對象自身相同的情況下,我們可以使用繼承加上聚合的方式來組合代碼,比如剛剛提到的例子中,

觀察一下,對于Boss來說,它的局部結(jié)構(gòu),即DevManager和FinanceManager與它自己的結(jié)構(gòu)有何區(qū)別?都是樹結(jié)構(gòu),無非就是根節(jié)點(diǎn)不一樣而已,所以于情于理這一塊可以用繼承加聚合來重構(gòu)
那么心細(xì)的朋友肯定發(fā)現(xiàn)了,有些操作是經(jīng)理類獨(dú)有的,這些操作我們是應(yīng)該抽象到和基層員工共同的父類雇員類嗎?對于這個(gè)問題,一般有兩種解決方案

透明型


在此設(shè)計(jì)中,子類方法的并集被提煉到了共有父類,哪怕這些方法對于某些子類根本不需要,這樣的好處是客戶端在使用的時(shí)候根本不需要知道對象糾結(jié)是哪個(gè)子類,對客戶端透明,所以得名。當(dāng)前設(shè)計(jì)多采用這種。

安全型

安全型設(shè)計(jì)非常保守,只會(huì)提煉子類交集的方法到父類,這樣的好處是絕對安全,客戶端絕對不可能在BasicLevelEmployee對象上面調(diào)用AddSubordinate或者RemoveSubordinate。但有時(shí)候會(huì)面臨向下轉(zhuǎn)型的情況。

重構(gòu)后的代碼(透明型)

抽象出共同父類雇員類,使用透明型,所有的子類方法都提煉到這個(gè)類

abstract class Employee
{
    public string ID { get; set; }
    public abstract void ShowStatus(int indent);
    //因?yàn)槭峭该餍?,所以基層員工用不上的方法也會(huì)被抽象到父類
    public abstract void AddSubordinate(Employee e);
    public abstract void RemoveSubordinate(Employee e);
}

對于基層員工,如果客戶端無意間調(diào)用了不該使用的方法,這基本是一個(gè)明確的、表明客戶端代碼出現(xiàn)了邏輯問題的信號(hào),這種情況直接拋出異常,能更快地暴露出問題

class BasicLevelEmployee : Employee
{
    public override void ShowStatus(int indent)
    {
        string str = ID;
        str = str.PadLeft(ID.Length + indent, '-');
        Console.WriteLine(str);
    }

    public override void AddSubordinate(Employee e)
    {
        throw new NotImplementedException();
    }
    public override void RemoveSubordinate(Employee e)
    {
        throw new NotImplementedException();
    }
}

在經(jīng)理類中,得益于共有父類Employee,我們可以用一個(gè)列表裝下所有的下屬,不論下屬是基層員工,還是經(jīng)理,抑或是未來可能添加的實(shí)習(xí)生。畢竟他們都是雇員嘛

class Manager : Employee
{
    public override void ShowStatus(int indent)
    {
        string str = ID;
        str = str.PadLeft(ID.Length + indent, '-');
        Console.WriteLine(str);
        indent += 4;
        Subordinate.ForEach(s => s.ShowStatus(indent));
    }
    public List<Employee> Subordinate = new List<Employee>();
    //下面是經(jīng)理所屬的方法
    public override void AddSubordinate(Employee e) { Subordinate.Add(e); }
    public override void RemoveSubordinate(Employee e) { Subordinate.Remove(e); }
}

公司架構(gòu)類和客戶端代碼調(diào)用保持不變,運(yùn)行結(jié)果一致,重構(gòu)成功。

可以看到,在使用了組合模式之后,現(xiàn)在的代碼不但消除了冗余(不用再去維護(hù)多個(gè)下屬列表),也更具有抵御未來變化的能力,這樣的結(jié)構(gòu)比起原來,當(dāng)然是更加合理的。這就是結(jié)構(gòu)型設(shè)計(jì)模式的用武之地,讓對象的結(jié)構(gòu)更加的合理,更加的易于擴(kuò)展。
這就是關(guān)于Composite組合模式的介紹,鑒于筆者能力有限,如果大家對于這篇文章中所講有其他看法,歡迎留言討論。

到此這篇關(guān)于C#中的composite模式的文章就介紹到這了,更多相關(guān)C# composite模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#生成Word文件(圖片、文字)

    C#生成Word文件(圖片、文字)

    這篇文章主要為大家詳細(xì)介紹了C#生成Word文件,包括圖片、文字等素材,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • c# 對cookies(增、刪、改、查)的操作方法

    c# 對cookies(增、刪、改、查)的操作方法

    以前覺得cookies操作無非就那么幾種,但是“杯具事件”還是很多的,下面分享一下對cookies的簡單操作
    2013-04-04
  • C#中加載dll并調(diào)用其函數(shù)的實(shí)現(xiàn)方法

    C#中加載dll并調(diào)用其函數(shù)的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄狢#中加載dll并調(diào)用其函數(shù)的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • C#如何生成唯一訂單號(hào)

    C#如何生成唯一訂單號(hào)

    這篇文章主要為大家詳細(xì)介紹了C#如何生成唯一訂單號(hào),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • c#事件使用示例詳解

    c#事件使用示例詳解

    這篇文章主要介紹了c#事件使用方法,下面我們利用一個(gè)例子來加深我們對事件的理解,需要的朋友可以參考下
    2014-04-04
  • C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法

    C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法

    這篇文章主要介紹了C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法,實(shí)例分析了C#中TreeView節(jié)點(diǎn)操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器

    C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器

    這篇文章主要介紹了C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器的相關(guān)代碼和使用方法,非常簡單實(shí)用,需要的朋友可以參考下
    2016-07-07
  • C#微信公眾號(hào)開發(fā)之自定義菜單

    C#微信公眾號(hào)開發(fā)之自定義菜單

    這篇文章介紹了C#微信公眾號(hào)開發(fā)之自定義菜單,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • C# #define條件編譯詳解

    C# #define條件編譯詳解

    這篇文章主要介紹了C# #define條件編譯,告訴大家#define是用來做什么?如何使用#define,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 在Linux上運(yùn)行C#的方法

    在Linux上運(yùn)行C#的方法

    這篇文章主要介紹了在Linux上運(yùn)行C#的方法,實(shí)例分析了Linux平臺(tái)下Mono軟件包的應(yīng)用技巧,以及在此基礎(chǔ)之上的C#運(yùn)行方法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12

最新評論