您的位置:首页 > 其它

设计模式系列漫谈之八 - 复合模式

2007-12-21 21:56 176 查看
故事
10月20日, 我们公司一行几人参加绍兴客户的项目招标。出乎意料的是,就在当天,这家单位同时举行三个项目的招标(真牛!),所以十几家单位都在等候。我们上午8:30就到了现场,而我们投标的项目去排在下午进行。傻坐了一会,我们提议到鲁迅故居去看看。其实几次去绍兴出差都匆匆忙忙的,今天终于如愿以偿。
近来确实锻炼太少,几个小时下来,我的脚又酸又痛,已经累得走不动了。不过,其中两幅图给我深刻的印象。一幅是三维立体效果的绍兴古城图,讲述着许多动人的故事;另一幅是周氏家族图,象一棵参天大树一样,枝枝蔓蔓。可以看出,鲁迅家族是浙江绍兴会稽县的一个大家族。鲁迅,原名周树人,他还有两个兄弟(周建人和周作人),他的父亲叫周伯宜,他有个儿子叫周海婴······,不说不了,再说就快晕了。

我在想一个可笑的问题,在整个周氏家族里,谁最能生儿子啊? 当然,我们没有这么多时间从头至尾数一遍。那么,就让我们用程序来解决吧。

复合模式(Composite)的解决方案
复合模式又叫部分-整体模式(Part-Whole)。将对象组织成树型结构(周氏家族图),可以用来描述整体与部分的关系,使客户端将单纯元素与复合元素同等看待,以此遍历树结构所有元素(所有周氏人)。复合模式需要定义三个对象:
抽象接口(IElement):这是一个抽象类/接口,它给所有对象定义接口,提供操作行为,如StatSons方法统计有多少个儿子。
组合(Composite)对象:代表包含子元素的组合。
元素(Element)对象:代表子元素对象。一个子元素没有下级子对象。

抽象接口如下:

namespace LuFamily
{
public interface IElement
{
string Name{get; set;}
void Add(IElement t);
void Remove(IElement t);
void StatSons();
}
}
组合对象如下:

namespace LuFamily
{
public class Composite:IElement
{
private List<IElement> elementList = new List<IElement>();

private string _Name;
public string Name
{
get{return _Name;}
set{_Name=value;}
}
public void Add(IElement t)
{
elementList.Add(t);
}
void Remove(IElement t)
{
elementList.Remove(t);
}
void StatSons()
{
Console.WriteLine(elementList.Count);

foreach(IElement element in elementList)
element.StatSons();
}
}
}
元素对象如下:

namespace LuFamily
{
public class Element:IElement
{
private string _Name;
public string Name
{
get{return _Name;}
set{_Name=value;}
}
public void Add(IElement t)
{
;
}
void Remove(IElement t)
{
;
}
void StatSons()
{
Console.WriteLine(0);
}
}
}
客户端调用如下:

Composite root=new Composite();
root.Name="周伯宜";

Element e1=new Element();
e1.Name="周建人";
root.Add(e1);

Element e2=new Element();
e2.Name="周作人";
root.Add(e1);

Composite c1=new Composite();
c1.Name="周树人";
root.Add(c1);

Element e3=new Element();
e3.Name="周海婴";
c1.Add(e3);

root.StatSons();

也许您会问,既然元素对象(Element)没有下级子对象,为什么还要实现Add和Remove方法呢?其实主要是为了实现客户端对元素对象与组合对象统一对待,而不必区分哪个是元素对象,哪个是组合对象,这是复合模式两种形式其中之一,即透明复合模式。采用这种方式的缺点是不够安全,因为在实际应用中,元素对象与组合对象存在着本质区别。

复合模式的另一种形式自然是安全复合模式。采用安全复合模式就是把元素对象与组合对象的在本质上区分开来。即元素对象不需要提供Add和Remove等元素集合的管理方法。让我们来看看安全复合模式的实现方法。

抽象接口如下:

namespace LuFamily
{
public interface IElement
{
string Name{get; set;}
void StatSons();
}
}
组合对象如下:

namespace LuFamily
{
public class Composite:IElement
{
private List<IElement> elementList = new List<IElement>();

private string _Name;
public string Name
{
get{return _Name;}
set{_Name=value;}
}
public void Add(IElement t)
{
elementList.Add(t);
}
void Remove(IElement t)
{
elementList.Remove(t);
}
void StatSons()
{
Console.WriteLine(elementList.Count);

foreach(IElement element in elementList)
element.StatSons();
}
}
}
元素对象如下:

namespace LuFamily
{
public class Element:IElement
{
private string _Name;
public string Name
{
get{return _Name;}
set{_Name=value;}
}
void StatSons()
{
Console.WriteLine(0);
}
}
}
客户端调用如下:

Composite root=new Composite();
root.Name="周伯宜";

Element e1=new Element();
e1.Name="周建人";
if (root is Composite)
root.Add(e1);

Element e2=new Element();
e2.Name="周作人";
if (root is Composite)
root.Add(e1);

Composite c1=new Composite();
c1.Name="周树人";
if (root is Composite)
root.Add(c1);

Element ce1=new Element();
ce1.Name="周海婴";
if (c1 is Composite)
c1.Add(ce1);

root.StatSons();
为了安全起见,执行Add方法的时候,最好判断是否为组合对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: