第37章
大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套娃這樣一堆娃娃,一個大的套一個小的,小的裏麵還可以套更小的,所以其組織結構為:
TopToy
Toy
——toy
——toy
——toy
大B:“如果用程序來描述套娃,用設計模式的組合模式(Composite)是一個不錯的主意。組合模式在GOF中定義為:組合(Composite)模式將對象以樹形結構組織起來,以達成‘部分-整體’的層次結構,使得客戶端對單個對象和組合對象的使用具有一致性。”
大B:“可以說,組合模式是比較簡單易學的設計模式,我按照其定義和規則,實現一個論壇主題,帖子的組合關係。論壇中,一個主題可以包括很多帖子,一個帖子還可以包括很多回複。”
關係是:
Thread
——Thread||Message
——Thread||Message
下麵是實現文件:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceCompositeStudy
{
publicinterfaceIThread
{
voidAdd(IThreadthread);
voidRemove(IThreadthread);
voidRenderContent();
}
}
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceCompositeStudy
{
publicabstractclassAbstractThread:IThread
{
boolisTop;
publicboolIsTop
{
get
{
returnisTop;
}
set
{
isTop=value;
}
}
List《IThread》list=newList《IThread》();
publicList《IThread》Children
{
get
{
returnlist;
}
set
{
list=value;
}
}
stringcontent=;
publicstringContent
{
get
{
returncontent;
}
set
{
content=value;
}
}
publicvoidAdd(IThreadthread)
{
list.Add(thread);
}
publicvoidRemove(IThreadthread)
{
list.Remove(thread);
}
publicabstractvoidRenderContent();
}
}
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceCompositeStudy
{
publicclassThread:AbstractThread
{
publicoverridevoidRenderContent()
{
//輸出自己的。
Console.WriteLine(Thread:+this.Content);
foreach(IThreadtinChildren)
{
t.RenderContent();
}
}
}
}
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceCompositeStudy
{
publicclassMessage:AbstractThread
{
publicoverridevoidRenderContent()
{
Console.WriteLine(Message:+this.Content);
foreach(IThreadtinChildren)
{
t.RenderContent();
}
}
}
}
工廠類為:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Data;
namespaceCompositeStudy
{
/**////《summary》
///工廠類
///《/summary》
///《remarks》工廠類《/remarks》
publicclassThreadFactory
{
DataTabletable=newDataTable();
publicThreadFactory()
{
table.Columns.Add(“content”);
table.Columns.Add(“IsTop”);
table.Columns.Add(“IsMessage”);
table.Columns.Add(“ID”);
table.Columns.Add(“ParentID”);
DataRowrow=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);
}
publicList《IThread》GetTopThreads()
{
List《IThread》list=newList《IThread》();
DataRow[]rows=table.Select(“IsTop=true”);
foreach(DataRowrowinrows)
{
Threadt=newThread();
t.Content=row[“content”].ToString();
t.IsTop=true;
DataRow[]cs=table.Select(“ParentID=”+Convert.ToInt32(row[“ID”]));
foreach(DataRowrincs)
{
if(Convert.ToBoolean(r[“IsMessage”]))
{
Messagem=newMessage();
m.Content=r[“content”].ToString();
m.IsTop=false;
t.Add(m);
}
else
{
Threadtt=newThread();
tt.Content=r[“content”].ToString();
tt.IsTop=false;
t.Add(tt);
}
}
list.Add(t);
}
returnlist;
}
}
}
客戶端調用方法為:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceCompositeStudy
{
classProgram
{
staticvoidMain(string[]args)
{
ThreadFactoryfactory=newThreadFactory();
List《IThread》threads=factory.GetTopThreads();
foreach(IThreadtinthreads)
{
t.RenderContent();
}
Console.Read();
}
}
}