窥视设计模式之组合模式(composite)
【IT168技术文档】经常使用Control,会发现Control有Controls的属性,而Controls集合包含的还是一个Control,类似的还有XmlNode.他们都有一个共有的特性,数据结构都是树行结构,什么是树形模式呢?
树(Tree)是n(n≥0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件:
(1) 有且仅有一个特定的称为根(Root)的结点;
(2) 其余的结点可分为m(m≥0)个互不相交的子集Tl,T2,…,Tm,其中每个子集本身又是一棵树,并称其为根的子树(SubTree)。上面给出的递归定义刻画了树的固有特性:一棵非空树是由若干棵子树构成的,而子树又可由若干棵更小的子树构成。而这里的子树可以是叶子也可以是分支。
先看下一幅图,里面的套娃就是一个套着一个的
这样一堆娃娃,一个大的套一个小的,小的里面还可以套更小的,所以其组织结构为:
Top Toy
- Toy
-- toy
----toy
----toy
如果用程序来描述上图,用设计模式的组合模式(Composite)是一个不错的主意
组合模式在GOF中定义为: 组合(Composite)模式将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
类图为:
可以说,组合模式是比较简单易学的设计模式,我按照其定义和规则,实现一个论坛主题,帖子的组合关系
论坛中,一个主题可以包括很多帖子 ,一个帖子还可以包括很多回复。关系是:
Thread
-- Thread||Message
-- Thread||Message
下面是实现文件:
类关系图:
输结果为:
通过该事例的调用,就可以知道,组合模式的好处有:
树(Tree)是n(n≥0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件:
(1) 有且仅有一个特定的称为根(Root)的结点;
(2) 其余的结点可分为m(m≥0)个互不相交的子集Tl,T2,…,Tm,其中每个子集本身又是一棵树,并称其为根的子树(SubTree)。上面给出的递归定义刻画了树的固有特性:一棵非空树是由若干棵子树构成的,而子树又可由若干棵更小的子树构成。而这里的子树可以是叶子也可以是分支。
先看下一幅图,里面的套娃就是一个套着一个的
这样一堆娃娃,一个大的套一个小的,小的里面还可以套更小的,所以其组织结构为:
Top Toy
- Toy
-- toy
----toy
----toy
如果用程序来描述上图,用设计模式的组合模式(Composite)是一个不错的主意
组合模式在GOF中定义为: 组合(Composite)模式将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
类图为:
可以说,组合模式是比较简单易学的设计模式,我按照其定义和规则,实现一个论坛主题,帖子的组合关系
论坛中,一个主题可以包括很多帖子 ,一个帖子还可以包括很多回复。关系是:
Thread
-- Thread||Message
-- Thread||Message
下面是实现文件:
工厂类为:1using System; 2using System.Collections.Generic; 3using System.Text; 4 5namespace CompositeStudy 6{ 7 public interface IThread 8 { 9 void Add(IThread thread); 10 void Remove(IThread thread); 11 void RenderContent(); 12 } 13} 14 15using System; 16using System.Collections.Generic; 17using System.Text; 18 19namespace CompositeStudy 20{ 21 public abstract class AbstractThread : IThread 22 { 23 bool _isTop; 24 public bool IsTop 25 { 26 get 27 { 28 return _isTop; 29 } 30 set 31 { 32 _isTop = value; 33 } 34 } 35 List<IThread> list = new List<IThread>(); 36 public List<IThread> Children 37 { 38 get 39 { 40 return list; 41 } 42 set 43 { 44 list = value; 45 } 46 } 47 string content = ""; 48 public string Content 49 { 50 get 51 { 52 return content; 53 } 54 set 55 { 56 content = value; 57 } 58 } 59 public void Add(IThread thread) 60 { 61 list.Add(thread); 62 } 63 public void Remove(IThread thread) 64 { 65 list.Remove(thread); 66 } 67 public abstract void RenderContent(); 68 } 69} 70 71 72using System; 73using System.Collections.Generic; 74using System.Text; 75 76namespace CompositeStudy 77{ 78 public class Thread : AbstractThread 79 { 80 81 public override void RenderContent() 82 { 83 //输出自己的Contetn 84 Console.WriteLine("Thread:"+this.Content); 85 foreach (IThread t in Children) 86 { 87 t.RenderContent(); 88 } 89 } 90 } 91} 92 93 94using System; 95using System.Collections.Generic; 96using System.Text; 97 98namespace CompositeStudy 99{ 100 public class Message:AbstractThread 101 { 102 public override void RenderContent() 103 { 104 Console.WriteLine("Message:" + this.Content); 105 foreach (IThread t in Children) 106 { 107 t.RenderContent(); 108 } 109 } 110 111 } 112}
客户端调用方法为:1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Data; 5 6namespace CompositeStudy 7{ 8 /**//// <summary> 9 /// 工厂类 10 /// </summary> 11 /// <remarks>工厂类</remarks> 12 public class ThreadFactory 13 { 14 DataTable table = new DataTable(); 15 public ThreadFactory() 16 { 17 table.Columns.Add("content"); 18 table.Columns.Add("IsTop"); 19 table.Columns.Add("IsMessage"); 20 table.Columns.Add("ID"); 21 table.Columns.Add("ParentID"); 22 23 DataRow row = table.NewRow(); 24 row["content"] = "test"; 25 row["IsTop"] = false; 26 row["IsMessage"] = false; 27 row["ID"] = 1; 28 row["ParentID"] = 0; 29 table.Rows.Add(row); 30 31 row = table.NewRow(); 32 row["content"] = "test1"; 33 row["IsTop"] = true; 34 row["IsMessage"] = false; 35 row["ID"] = 0; 36 row["ParentID"] = -1; 37 table.Rows.Add(row); 38 39 row = table.NewRow(); 40 row["content"] = "test2"; 41 row["IsTop"] = false; 42 row["IsMessage"] = true; 43 row["ID"] = 2; 44 row["ParentID"] = 0; 45 table.Rows.Add(row); 46 47 row = table.NewRow(); 48 row["content"] = "test3"; 49 row["IsTop"] = false; 50 row["IsMessage"] = true; 51 row["ID"] = 3; 52 row["ParentID"] = 0; 53 table.Rows.Add(row); 54 } 55 public List<IThread> GetTopThreads() 56 { 57 List<IThread> list = new List<IThread>(); 58 DataRow[] rows = table.Select("IsTop = true"); 59 foreach (DataRow row in rows) 60 { 61 Thread t = new Thread(); 62 t.Content = row["content"].ToString(); 63 t.IsTop = true; 64 DataRow[] cs = table.Select("ParentID="+Convert.ToInt32(row["ID"])); 65 foreach (DataRow r in cs) 66 { 67 if (Convert.ToBoolean(r["IsMessage"])) 68 { 69 Message m = new Message(); 70 m.Content = r["content"].ToString(); 71 m.IsTop = false; 72 t.Add(m); 73 } 74 else 75 { 76 Thread tt = new Thread(); 77 tt.Content = r["content"].ToString(); 78 tt.IsTop = false; 79 t.Add(tt); 80 } 81 } 82 list.Add(t); 83 } 84 return list; 85 } 86 } 87}
1using System; 2using System.Collections.Generic; 3using System.Text; 4 5namespace CompositeStudy 6{ 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 ThreadFactory factory = new ThreadFactory(); 12 List<IThread> threads = factory.GetTopThreads(); 13 foreach(IThread t in threads) 14 { 15 t.RenderContent(); 16 } 17 Console.Read(); 18 } 19 } 20} 21
类关系图:
输结果为:
通过该事例的调用,就可以知道,组合模式的好处有:
1) 使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2) 更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利!
0
相关文章