窥视设计模式之组合模式(composite)

经常使用Control,会发现Control有Controls的属性,而Controls集合包含的还是一个Control,类似的还有XmlNode.他们都有一个共有的特性,数据结构都是树行结构,什么是树形模式呢?
(Tree)n(n≥0)个结点的有限集TT为空时称为空树,否则它满足如下两个条件:
(1)    有且仅有一个特定的称为根(Root)的结点;
(2)   其余的结点可分为m(m≥0)个互不相交的子集TlT2Tm,其中每个子集本身又是一棵树,并称其为根的子树(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}

113
114

工厂类为:
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4 using  System.Data;
 5
 6 namespace  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}

88

客户端调用方法为:
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4
 5 namespace  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)       更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利!


你可能感兴趣的:(窥视设计模式之组合模式(composite))