??簡(jiǎn)介
?
??角色
- 抽象根節(jié)點(diǎn)(Component):定義系統(tǒng)各層次對(duì)象的共有方法和屬性,可以預(yù)先定義一些默認(rèn)行為和屬性。
- 樹枝節(jié)點(diǎn)(Composite):定義樹枝節(jié)點(diǎn)的行為,存儲(chǔ)子節(jié)點(diǎn),組合樹枝節(jié)點(diǎn)和葉子節(jié)點(diǎn)形成一個(gè)樹形結(jié)構(gòu)。
- 葉子節(jié)點(diǎn)(Leaf):葉子節(jié)點(diǎn)對(duì)象,其下再無(wú)分支,是系統(tǒng)層次遍歷的最小單位。
??與我們上圖中文件系統(tǒng)圖例對(duì)應(yīng)
- 抽象根節(jié)點(diǎn) = 最頂部的文件夾
- 樹枝節(jié)點(diǎn) = 文件夾
- 葉子節(jié)點(diǎn) = 文件
??案例
不管是菜單還是菜單項(xiàng),都應(yīng)該繼承自統(tǒng)一的接口,這里我們創(chuàng)建一個(gè)抽象組件,定義一些通用的方法,如添加,刪除,打印。
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);
}
??樹枝節(jié)點(diǎn)Composite
定義一個(gè)名為children的List類型的列表,用于存儲(chǔ)Component類型的子元素,Add方法和Remove方法分別用于向children列表中添加和移除Component類型的對(duì)象。Display方法用于顯示Composite對(duì)象的信息。這個(gè)方法首先打印出當(dāng)前Composite對(duì)象的深度和名稱,然后遍歷children列表,對(duì)每個(gè)子元素調(diào)用Display方法。這樣就形成了一種遞歸的結(jié)構(gòu),可以用來(lái)表示樹形結(jié)構(gòu)。
public class Composite : Component
{
private List<Component> children = new List<Component>();
public Composite(string name)
: base(name)
{
}
public override void Add(Component component)
{
children.Add(component);
}
public override void Remove(Component component)
{
children.Remove(component);
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + _name);
foreach (Component component in children)
{
component.Display(depth + 2);
}
}
}
??葉子節(jié)點(diǎn)Leaf
因?yàn)槿~子節(jié)點(diǎn)已經(jīng)是最下級(jí)了,因此我們只需要在Display直接重寫打印方法,并且不需要再進(jìn)行遍歷了
public class Leaf : Component
{
public Leaf(string name)
: base(name)
{
}
public override void Add(Component c)
{
Console.WriteLine("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + _name);
}
}
??測(cè)試
class MyClass
{
public static void Main(string[] args)
{
// 創(chuàng)建一個(gè)根節(jié)點(diǎn)
Component root = new Composite("root");
// 創(chuàng)建兩個(gè)節(jié)點(diǎn)
Component node1 = new Composite("node1");
Component node2 = new Composite("node2");
// 創(chuàng)建葉子節(jié)點(diǎn)
Component leaf1 = new Leaf("leaf1");
Component leaf2 = new Leaf("leaf2");
Component leaf3 = new Leaf("leaf3");
// 構(gòu)建樹形結(jié)構(gòu)
root.Add(node1);
root.Add(node2);
node1.Add(leaf1);
node2.Add(leaf2);
node2.Add(leaf3);
// 顯示樹形結(jié)構(gòu)
root.Display(1);
}
}
運(yùn)行結(jié)果!在這個(gè)例子中,我們首先創(chuàng)建了一個(gè)根節(jié)點(diǎn)root
,然后創(chuàng)建了兩個(gè)節(jié)點(diǎn)node1
和node2
,以及三個(gè)葉子節(jié)點(diǎn)leaf1
,leaf2
和leaf3
。然后我們將node1
和node2
添加到root
下,將leaf1
添加到node1
下,將leaf2
和leaf3
添加到node2
下,從而構(gòu)建了一個(gè)樹形結(jié)構(gòu)。
??總結(jié)
??優(yōu)點(diǎn)
- 組合模式可以清楚地定義分層次的復(fù)雜對(duì)象,表示對(duì)象的全部或部分層次,它讓客戶端忽略了層次的差異,方便對(duì)整個(gè)層次結(jié)構(gòu)進(jìn)行控制。
- 客戶端可以一致地使用一個(gè)組合結(jié)構(gòu)或其中單個(gè)對(duì)象,不必關(guān)心處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu),簡(jiǎn)化了客戶端代碼。
- 在組合模式中增加新的樹枝節(jié)點(diǎn)和葉子節(jié)點(diǎn)都很方便,無(wú)須對(duì)現(xiàn)有類庫(kù)進(jìn)行任何修改,符合“開閉原則”。
- 組合模式為樹形結(jié)構(gòu)的面向?qū)ο髮?shí)現(xiàn)提供了一種靈活的解決方案,通過(guò)葉子節(jié)點(diǎn)和樹枝節(jié)點(diǎn)的遞歸組合,可以形成復(fù)雜的樹形結(jié)構(gòu),但對(duì)樹形結(jié)構(gòu)的控制卻非常簡(jiǎn)單。
??缺點(diǎn)
????????在使用組合模式時(shí),其葉子和樹枝的聲明都是實(shí)現(xiàn)類,而不是接口,違反了依賴倒置原則。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-729327.html
??使用場(chǎng)景
????????組合模式正是應(yīng)樹形結(jié)構(gòu)而生,所以組合模式的使用場(chǎng)景就是出現(xiàn)樹形結(jié)構(gòu)的地方。比如:文件目錄顯示,多級(jí)目錄呈現(xiàn)等樹形結(jié)構(gòu)數(shù)據(jù)的操作。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-729327.html
到了這里,關(guān)于c#設(shè)計(jì)模式-結(jié)構(gòu)型模式 之 組合模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!