2.4設(shè)計(jì)模式之組合模式(Composite)

2.4.1 模式意圖:

在處理樹形結(jié)構(gòu)數(shù)據(jù)時(shí),通常必須區(qū)分葉節(jié)點(diǎn)和分支節(jié)點(diǎn)。這使代碼更復(fù)雜,也更容易出錯(cuò)糊治。組合模式模糊了葉節(jié)點(diǎn)和分支節(jié)點(diǎn)的概念,可以使葉節(jié)點(diǎn)和分支節(jié)點(diǎn)以單一對象的方式統(tǒng)一處理罚舱,且所有節(jié)點(diǎn)對象均具有相似的功能井辜。

2.4.2 模式概念:

它屬于結(jié)構(gòu)型模式,將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)管闷。組合模式使得用戶對單個(gè)對象和組合對象的使用具有一致性粥脚。

2.4.3 模式元素:

  • 節(jié)點(diǎn)抽象(CompsiteBase)
  • 葉子節(jié)點(diǎn)(Leaf)
  • 復(fù)合節(jié)點(diǎn)(Composite)

2.4.4 代碼示例:

示例相對簡單,就是一個(gè)樹狀的結(jié)構(gòu)包个,一個(gè)主干刷允,然后就是分支,每個(gè)分支可能是葉子節(jié)點(diǎn)碧囊,也可能是含有子分支的節(jié)點(diǎn)树灶。

A.創(chuàng)建一個(gè)節(jié)點(diǎn)的抽象基類 ,也就是每個(gè)節(jié)點(diǎn)基類

    public abstract class CompsiteBase
    {
        protected string name;

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

        public abstract void Add(CompsiteBase c);
        public abstract void Remove(CompsiteBase c);
        public abstract void Display(int depth);
    }

B.葉子節(jié)點(diǎn)天通,也就是不含子節(jié)點(diǎn)的分支

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

    public override void Add(CompositeBase c)
    {
        Debug.Log("Cannot add to a leaf");
    }

    public override void Remove(CompositeBase c)
    {
        Debug.Log("Cannot remove from a leaf");
    }

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

C.含有子節(jié)點(diǎn)的分支

public class Composite : CompositeBase
{
    private List<CompsiteBase> children = new List<CompsiteBase>();

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

    public override void Add(CompositeBase c)
    {
        children.Add(c);
    }

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

    public override void Display(int depth)
    {
        Debug.Log(new String('-', depth) + name);

        foreach (CompositeBase composite in children)
        {
            compsite.Display(depth + 2);
        }
    }
}

示例調(diào)用

    void Start()
    {
        Composite root = new Composite("root");
        root.Add(new Leaf("Leaf A"));
        root.Add(new Leaf("Leaf B"));

        Composite comp = new Composite("Composite X");
        comp.Add(new Leaf("Leaf XA"));
        comp.Add(new Leaf("Leaf XB"));

        root.Add(comp);

        Composite comp2 = new Composite("Composite XY");
        comp2.Add(new Leaf("Leaf XYA"));
        comp2.Add(new Leaf("Leaf XYB"));

        comp.Add(comp2);

        root.Add(new Leaf("Leaf C"));

        Leaf leaf = new Leaf("Leaf D");
        root.Add(leaf);
        root.Remove(leaf);

        root.Display(1);
    }

2.4.5 寫法對比:

2.4.6 模式分析:

通過CompositeBase接口來統(tǒng)一處理LeafComposite對象: Leaf對象直接執(zhí)行請求,而Composite對象將請求以遞歸的方式向下傳遞到樹結(jié)構(gòu)的子節(jié)點(diǎn)携悯。這使得類更易于實(shí)現(xiàn)、更改逊彭、測試和重用避矢。

組合模式也分為安全模式透明模式

  • 安全模式:在抽象基類中沒有提供 Add Remove等管理子節(jié)點(diǎn)的函數(shù)。
    優(yōu)點(diǎn):不必實(shí)現(xiàn)不需要的相關(guān)函數(shù)烫扼。
    缺點(diǎn):需要區(qū)分葉子節(jié)點(diǎn)和含有子節(jié)點(diǎn)的分支,進(jìn)行分別調(diào)用。
  • 透明模式:與安全模式相反双絮,含有對應(yīng)管理子節(jié)點(diǎn)的函數(shù)。
    優(yōu)點(diǎn):可以統(tǒng)一的調(diào)用焚挠。
    缺點(diǎn):容易錯(cuò)誤調(diào)用相關(guān)的管理函數(shù)而引發(fā)異常。

2.4.7 應(yīng)用場景:

  • 整體部分的層次為樹結(jié)構(gòu)挟鸠,且需要統(tǒng)一對待部分和整體對象。

2.4.8 小結(jié):

當(dāng)你發(fā)現(xiàn)需求是體現(xiàn)部分與整體層次結(jié)構(gòu)時(shí),以及你希望用戶可以忽律組合對象與單個(gè)對象的不同,統(tǒng)一地使用組合結(jié)構(gòu)中的所有對象凤壁,就可以考慮使用組合模式了免绿。


更多設(shè)計(jì)模式詳見:設(shè)計(jì)模式全家桶

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绞绒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖谬晕,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件不撑,死亡現(xiàn)場離奇詭異晤斩,居然都是意外死亡焕檬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烹俗,“玉大人蕉鸳,你說我怎么就攤上這事勉失⊙氏遥” “怎么了徒蟆?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闹蒜。 經(jīng)常有香客問我寺枉,道長抑淫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任姥闪,我火速辦了婚禮丈冬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甘畅。我一直安慰自己埂蕊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布疏唾。 她就那樣靜靜地躺著蓄氧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪槐脏。 梳的紋絲不亂的頭發(fā)上喉童,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音顿天,去河邊找鬼堂氯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛牌废,可吹牛的內(nèi)容都是我干的咽白。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鸟缕,長吁一口氣:“原來是場噩夢啊……” “哼晶框!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懂从,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤授段,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后番甩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侵贵,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年缘薛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窍育。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掩宜,死狀恐怖蔫骂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牺汤,我是刑警寧澤辽旋,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響补胚,放射性物質(zhì)發(fā)生泄漏码耐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一溶其、第九天 我趴在偏房一處隱蔽的房頂上張望骚腥。 院中可真熱鬧,春花似錦瓶逃、人聲如沸束铭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽契沫。三九已至,卻和暖如春昔汉,著一層夾襖步出監(jiān)牢的瞬間懈万,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工靶病, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留会通,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓娄周,卻偏偏與公主長得像涕侈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子昆咽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容