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

2.4.1 模式意圖:

在處理樹(shù)形結(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)以單一對(duì)象的方式統(tǒng)一處理,且所有節(jié)點(diǎn)對(duì)象均具有相似的功能。

2.4.2 模式概念:

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

2.4.3 模式元素:

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

2.4.4 代碼示例:

示例相對(duì)簡(jiǎn)單,就是一個(gè)樹(shù)狀的結(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 寫(xiě)法對(duì)比:

2.4.6 模式分析:

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

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

  • 安全模式:在抽象基類中沒(méi)有提供 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)用。
  • 透明模式:與安全模式相反,含有對(duì)應(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)用場(chǎng)景:

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

2.4.8 小結(jié):

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


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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容