合成模式从字面上来理解即一个对象由其它几N个象组合而成,其N>=1(为什么说N会有时等于1呢,我是这么理解的,当一个对象中包括另一个对象时,它所包括的对象又包括N个其它对象,依次下去,可以看去与这个对象相关的对象会有M个这里M>1,但对象本身相对于它所包含的对象来说有只包含了一个)。多数关于Composite模式的文章都是与树结构相关联,这却是形容得太适合不过了,所以本文也不例外:
先看看树的构成:
我们在学数据结构时就知道树是由树枝节点与树叶构成,树枝节点可以有子的树枝节点与树叶,但树叶却不能有子的树枝节点或子的树叶。
下面是构成树的类图:
从图中可以看去子树枝下又可以包含多少树枝,依次这么下去,也就是我上面所说的对象中包含子对象,子对象又包含对象。[看上去有点像递归:)]
合成模式根据树枝(抽象类或接口)是否对子树枝进行管理可分为为安全模式和透明模式; 安全模式去在树枝中不提供对子树枝的管理,而让子树枝自己去管理自己,在这种模式下,因子树枝与树叶都是继承自树枝所以让子树枝自己去管理自己对于树叶来说是安全的; 透明模式去在树枝中对子树技进行管理,这样使得子树枝与树叶都具有相同的接口,相对而言子树枝与树叶之间是透明的。但对于树叶而言因没有子树枝,所以树叶去管理时会抛去异常。
下面来看看我用透明模式实现的一个树结构:
/// <summary>
/// 樹
/// </summary>
abstract public class Tree
{
protected string m_strName;
public Tree(string name)
{
this.m_strName = name;
}
public string Name
{
get{return m_strName;}
}
abstract public void Add(Tree n);//增加子節點
abstract public void Remove(Tree n);//刪除子節點
abstract public ArrayList Children();//獲得所有子節點
abstract public Tree GetChild(string name);//獲得指定名稱的節點
abstract public string Display(int depth);//顯示
}
/// <summary>
/// 節點
/// </summary>
public class Node : Tree
{
private ArrayList m_arrayChildren = new ArrayList();
public Node(string name) : base(name){}
public override void Add(Tree n)
{
m_arrayChildren.Add(n);
}
public override void Remove(Tree n)
{
m_arrayChildren.Remove(n);
}
public override string Display(int depth)
{
string tmp = new String('-',depth) + m_strName;
foreach(Tree n in m_arrayChildren)
{
tmp+=n.Display(depth+1);
}
return tmp;
}
public override ArrayList Children()
{
return m_arrayChildren;
}
public override Tree GetChild(string name)
{
Tree tree = null;
foreach(Tree n in m_arrayChildren)
{
if(n.Name==name)
{
tree = n;
break;
}
}
return tree;
}
}
/// <summary>
/// 葉子
/// </summary>
public class Leaf : Tree
{
public Leaf(string name) :base(name){}
public override string Display(int depth)
{
return new String('-',depth) + m_strName;
}
public override void Add(Tree n)
{
throw new Exception("葉子節點不能存在子節點");
}
public override void Remove(Tree n)
{
throw new Exception("葉子節點不存在子節點");
}
public override ArrayList Children()
{
return null;
}
public override Tree GetChild(string name)
{
return null;
}
}
/// 樹
/// </summary>
abstract public class Tree
{
protected string m_strName;
public Tree(string name)
{
this.m_strName = name;
}
public string Name
{
get{return m_strName;}
}
abstract public void Add(Tree n);//增加子節點
abstract public void Remove(Tree n);//刪除子節點
abstract public ArrayList Children();//獲得所有子節點
abstract public Tree GetChild(string name);//獲得指定名稱的節點
abstract public string Display(int depth);//顯示
}
/// <summary>
/// 節點
/// </summary>
public class Node : Tree
{
private ArrayList m_arrayChildren = new ArrayList();
public Node(string name) : base(name){}
public override void Add(Tree n)
{
m_arrayChildren.Add(n);
}
public override void Remove(Tree n)
{
m_arrayChildren.Remove(n);
}
public override string Display(int depth)
{
string tmp = new String('-',depth) + m_strName;
foreach(Tree n in m_arrayChildren)
{
tmp+=n.Display(depth+1);
}
return tmp;
}
public override ArrayList Children()
{
return m_arrayChildren;
}
public override Tree GetChild(string name)
{
Tree tree = null;
foreach(Tree n in m_arrayChildren)
{
if(n.Name==name)
{
tree = n;
break;
}
}
return tree;
}
}
/// <summary>
/// 葉子
/// </summary>
public class Leaf : Tree
{
public Leaf(string name) :base(name){}
public override string Display(int depth)
{
return new String('-',depth) + m_strName;
}
public override void Add(Tree n)
{
throw new Exception("葉子節點不能存在子節點");
}
public override void Remove(Tree n)
{
throw new Exception("葉子節點不存在子節點");
}
public override ArrayList Children()
{
return null;
}
public override Tree GetChild(string name)
{
return null;
}
}
在客戶端的實現:
合成模式
如有什麼講得不當的地方還請各位指出,非常感謝!