书城计算机大话设计模式
11030400000037

第37章 6 树

大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();

}

}

}