動機:客戶代碼過多地依賴於對象容器複雜的內部實現結構,對象容器內部實現結構(而非抽象介面)的變化將引起客戶代碼的頻繁變化,帶來了代碼維護性、擴充性等弊端。本模式通過將對象組合成樹形結構以表示“部分-整體”的階層,讓組合對象實現自身的複雜結構,使得使用者對單個對象和組合對象的使用具有一致性。
應用:ASP.NET子父控制項關係。
情境:以樹為例,葉子為最低級原子節點,樹為容器,可以包括子樹和葉子。需要使客戶程式對樹和葉子的處理一致,保持透明性,而不需要關心處理的是樹還是葉子。
結構:
代碼實現
namespace DesignPattern.Composite
{
public interface ITree
{
void Process();
void Add(ITree tree);
void Remove(ITree tree);
}
public class Leaf : ITree
{
public void Process()
{
}
public void Add(ITree tree)
{
throw new Exception("葉子不支援該方法!");
}
public void Remove(ITree tree)
{
throw new Exception("葉子不支援該方法!");
}
}
public class Tree : ITree
{
IList<ITree> treeCollection = null;
public void Process()
{
foreach (ITree tree in treeCollection)
{
tree.Process();
}
}
public void Add(ITree tree)
{
treeCollection.Add(tree);
}
public void Remove(ITree tree)
{
treeCollection.Remove(tree);
}
}
}
/**//*
* 樹工廠
*/
namespace DesignPattern.Composite
{
public class TreeFactory
{
public static ITree GetTree()
{
return (ITree)Assembly.Load("DesignPattern.Composite").CreateInstance("DesignPattern.Composite" + "." + System.Configuration.ConfigurationSettings.AppSettings["TreeName"].ToString());
}
}
}
/**//*
* 客戶程式
*/
namespace DesignPattern.Composite
{
public class TreeClient
{
ITree tree;
public TreeClient()
{
tree = TreeFactory.GetTree();
}
public void ProcessTree()
{
// 客戶代碼依賴抽象介面
tree.Process();
}
}
}
要點:
1、本模式採用樹形結構來實現普遍存在的對象容器,從而將“一對多” 的關係轉化為“一對一”的關係,使得客戶代碼可以一致地處理單個對象和對象容器,而無需關心處理的是單個對象還是組合的對象容器。
2、將“客戶代碼與複雜的對象容器結構”解耦是本模式的核心思想,解耦之後,客戶代碼將與純粹的抽象介面——而非對象容器的複雜內部實現結構——發生依賴關係,從而能夠應對變化。
3、本模式中,將單個對象不具有的操作的(如Add和Remove)定義於介面或抽象類別中,還是組合對象中,需要從透明性和安全性兩方面平衡考慮。應用此模式,更強調透明性,所以有可能違背物件導向的“單一職責”原則。
4、本模式在具體實現中,可以讓父物件中的子物件反向追溯;如果父物件有頻繁的遍曆需求,可使用緩衝來改善效能。