四個角色:部件抽象接口角色(Component)、葉角色(Leaf)、組合類角色(Composite)、用戶端角色(Client)
部件抽象接口角色(Component):定義組合類對象的公共行為、屬性和管理子部件的方法接口。
葉角色(Leaf):實作Component的公共行為,但是無法管理子部件,為最終葉節點。
組合類角色(Composite):實作Component的公共行為,可以管理子節點(增、删、查)。
用戶端角色(Client):通過Component控制整棵組合對象樹。
實作思路:一棵樹,分為葉節點和主幹節點,通過一個統一的接口可以往下添加節點和删除節點。
類圖:
<a target="_blank" href="http://blog.51cto.com/attachment/201204/155407950.jpg"></a>
應用場景:Silverlight中一個Canvas名為Layout,需要有很多行,第一行 是一個TextBox,第二行是一個RichTextBox,第三行是RadioButton,第四行是一個複雜的組合控件名為complex其内部有 RadioButtonA、ComboBoxB、TextBoxC三個子控件。
分析:這裡實際上可以看做是一棵樹型結構的容器Layout,内部有4個控件,其中3個簡單控件是葉節點,最後一個複雜控件是主幹,主幹下面還有3個葉片節點。
下面我們在控制台程式去示範一下如何使用Composite Pattern:
一、部件抽象接口角色(Component)
//部件抽象接口角色:Component
abstract class ControlComponent
{
public string ControlName { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public int AllowInputNum { get; set; }
abstract public void AddNode(ControlComponent con);
abstract public void RemoveNode(ControlComponent con);
abstract public void ShowNodeInfo();
}
二、葉角色(Leaf)
//葉角色:Leaf
class ControlLeaf : ControlComponent
{
//葉角色沒有子節點,故不能添加删除子節點
public override void AddNode(ControlComponent con)
{
Console.WriteLine("葉類無法添加子節點。");
}
public override void RemoveNode(ControlComponent con)
Console.WriteLine("葉類無法移出子節點。");
//顯示子節點資訊的方法
public override void ShowNodeInfo()
Console.WriteLine("___控件名:" + ControlName + " 控件寬度:" + Width + " 控件高度:" + Height + " 控件允許輸入:" + AllowInputNum);
}
三、組合類角色(Composite)
//組合類:Composite(主幹類)
class ControlComposite : ControlComponent
//子節點的容器(可以是葉節點,葉可以是下一節主幹)
private List<ControlComponent> controlList = new List<ControlComponent>();
//添加和删除子節點
controlList.Add(con);
controlList.Remove(con);
//顯示子節點
Console.WriteLine("控件名:" + ControlName + " 控件寬度:" + Width + " 控件高度:" + Height + " 控件允許輸入:" + AllowInputNum);
//遞歸顯示其子節點樹
foreach (ControlComponent c in controlList)
{
c.ShowNodeInfo();
}
四、用戶端角色(Client)
//用戶端:Client
class Program
static void Main(string[] args)
{
ControlComposite controlLayout = new ControlComposite() { ControlName = "Layout", Height = 300, Width = 300 };
controlLayout.AddNode(new ControlLeaf() { ControlName = "___TextBox", Height = 30, Width = 180, AllowInputNum = 50 });
controlLayout.AddNode(new ControlLeaf() { ControlName = "___RichTextBox", Height = 35, Width = 220, AllowInputNum = 1000 });
controlLayout.AddNode(new ControlLeaf() { ControlName = "___RadioButton", Height = 25, Width = 300, AllowInputNum = 1 });
ControlComposite complexControl = new ControlComposite() { ControlName = "complex", Height = 96, Width = 300 };
complexControl.AddNode(new ControlLeaf() { ControlName = "___RadioButtonA", Height = 33, Width = 180, AllowInputNum = 50 });
complexControl.AddNode(new ControlLeaf() { ControlName = "___ComboBoxB", Height = 33, Width = 100 });
complexControl.AddNode(new ControlLeaf() { ControlName = "___TextBoxC", Height = 30, Width = 100 });
controlLayout.AddNode(complexControl);
// controlLayout.RemoveNode(complexControl);
controlLayout.ShowNodeInfo();
Console.ReadLine();
}
本文轉自程興亮 51CTO部落格,原文連結:http://blog.51cto.com/chengxingliang/826952