大B:“经常使用Control,你会发现Control有Controls的属性,而Controls集合包含的还是一个Control,类似的还有XmlNode。他们都有一个共有的特性,数据结构都是树行结构。”
小A:“什么是树形模式呢?”
大B:“树(Tree)是n(n≥0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件:1、有且仅有一个特定的称为根(Root)的结点;2、其余的结点可分为m(m≥0)个互不相交的子集Tl,T2……,Tm,其中每个子集本身又是一棵树,并称其为根的子树(SubTree)。”
大B:“上面给出的递归定义刻画了树的固有特性:一棵非空树是由若干棵子树构成的,而子树又可由若干棵更小的子树构成。而这里的子树可以是叶子也可以是分支。先看下一幅图,里面的套娃就是一个套着一个的。”图5-2套娃这样一堆娃娃,一个大的套一个小的,小的里面还可以套更小的,所以其组织结构为:
Top Toy
Toy
――toy
――toy
――toy
大B:“如果用程序来描述套娃,用设计模式的组合模式(Composite)是一个不错的主意。组合模式在GOF中定义为:组合(Composite)模式将对象以树形结构组织起来,以达成‘部分-整体’的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。”
大B:“可以说,组合模式是比较简单易学的设计模式,我按照其定义和规则,实现一个论坛主题,帖子的组合关系。论坛中,一个主题可以包括很多帖子,一个帖子还可以包括很多回复。”
关系是:
Thread
――Thread||Message
――Thread||Message
下面是实现文件:
using System;
using System。Collections。Generic;
using System。Text;
namespace CompositeStudy
{
public interface IThread
{
void Add(IThread thread);
void Remove(IThread thread);
void RenderContent();
}
}
using System;
using System。Collections。Generic;
using System。Text;
namespace CompositeStudy
{
public abstract class AbstractThread:IThread
{
boolisTop;
public bool IsTop
{
get
{
returnisTop;
}
set
{
isTop=value;
}
}
List《IThread》list=new List《IThread》();
public List《IThread》Children
{
get
{
return list;
}
set
{
list=value;
}
}
string content=;
public string Content
{
get
{
return content;
}
set
{
content=value;
}
}
public void Add(IThread thread)
{
list。Add(thread);
}
public void Remove(IThread thread)
{
list。Remove(thread);
}
public abstract void RenderContent();
}
}
using System;
using System。Collections。Generic;
using System。Text;
namespace CompositeStudy
{
public class Thread:AbstractThread
{
public override void RenderContent()
{
//输出自己的。
Console。WriteLine(Thread: this。Content);
foreach(IThread t in Children)
{
t。RenderContent();
}
}
}
}
using System;
using System。Collections。Generic;
using System。Text;
namespace CompositeStudy
{
public class Message:AbstractThread
{
public override void RenderContent()
{
Console。WriteLine(Message: this。Content);
foreach(IThread t in Children)
{
t。RenderContent();
}
}
}
}
工厂类为:
using System;
using System。Collections。Generic;
using System。Text;
using System。Data;
namespace CompositeStudy
{
/**////《summary》
///工厂类
///《/summary》
///《remarks》工厂类《/remarks》
public class ThreadFactory
{
DataTable table=new DataTable();
public ThreadFactory()
{
table。Columns。Add(“content”);
table。Columns。Add(“IsTop”);
table。Columns。Add(“IsMessage”);
table。Columns。Add(“ID”);
table。Columns。Add(“ParentID”);
DataRow row=table。NewRow();
row[“content”]=“test”;
row[“IsTop”]=false;
row[“IsMessage”]=false;
row[“ID”]=1;
row[“ParentID”]=0;
table。Rows。Add(row);
row=table。NewRow();
row[“content”]=“test1”;
row[“IsTop”]=true;
row[“IsMessage”]=false;
row[“ID”]=0;
row[“ParentID”]=-1;
table。Rows。Add(row);
row=table。NewRow();
row[“content”]=“test2”;
row[“IsTop”]=false;
row[“IsMessage”]=true;
row[“ID”]=2;
row[“ParentID”]=0;
table。Rows。Add(row);
row=table。NewRow();
row[“content”]=“test3”;
row[“IsTop”]=false;
row[“IsMessage”]=true;
row[“ID”]=3;
row[“ParentID”]=0;
table。Rows。Add(row);
}
public List《IThread》GetTopThreads()
{
List《IThread》list=new List《IThread》();
DataRow[]rows=table。Select(“IsTop=true”);
foreach(DataRow row in rows)
{
Thread t=new Thread();
t。Content=row[“content”]。ToString();
t。IsTop=true;
DataRow[]cs=table。Select(“ParentID=” Convert。ToInt32(row[“ID”]));
foreach(DataRow r in cs)
{
if(Convert。ToBoolean(r[“IsMessage”]))
{
Message m=new Message();
m。Content=r[“content”]。ToString();
m。IsTop=false;
t。Add(m);
}
else
{
Thread tt=new Thread();
tt。Content=r[“content”]。ToString();
tt。IsTop=false;
t。Add(tt);
}
}
list。Add(t);
}
return list;
}
}
}
客户端调用方法为:
using System;
using System。Collections。Generic;
using System。Text;
namespace CompositeStudy
{
class Program
{
static void Main(string[]args)
{
ThreadFactory factory=new ThreadFactory();
List《IThread》threads=factory。GetTopThreads();
foreach(IThread t in threads)
{
t。RenderContent();
}
Console。Read();
}
}
}