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

经常使用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
下面是实现文件:

ContractedBlock.gif ExpandedBlockStart.gif
  1None.gifusing System;
  2None.gifusing System.Collections.Generic;
  3None.gifusing System.Text;
  4None.gif
  5None.gifnamespace CompositeStudy
  6ExpandedBlockStart.gifContractedBlock.gifdot.gif{
  7InBlock.gif    public interface IThread
  8ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
  9InBlock.gif        void Add(IThread thread);
 10InBlock.gif        void Remove(IThread thread);
 11InBlock.gif        void RenderContent();
 12ExpandedSubBlockEnd.gif    }

 13ExpandedBlockEnd.gif}

 14None.gif
 15None.gifusing System;
 16None.gifusing System.Collections.Generic;
 17None.gifusing System.Text;
 18None.gif
 19None.gifnamespace CompositeStudy
 20ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 21InBlock.gif    public abstract class AbstractThread : IThread
 22ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 23InBlock.gif        bool _isTop;
 24InBlock.gif        public bool IsTop
 25ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 26InBlock.gif            get
 27ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 28InBlock.gif                return _isTop;
 29ExpandedSubBlockEnd.gif            }

 30InBlock.gif            set
 31ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 32InBlock.gif                _isTop = value;
 33ExpandedSubBlockEnd.gif            }

 34ExpandedSubBlockEnd.gif        }

 35InBlock.gif        List<IThread> list = new List<IThread>();
 36InBlock.gif        public List<IThread> Children
 37ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 38InBlock.gif            get
 39ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 40InBlock.gif                return list;
 41ExpandedSubBlockEnd.gif            }

 42InBlock.gif            set
 43ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 44InBlock.gif                list = value;
 45ExpandedSubBlockEnd.gif            }

 46ExpandedSubBlockEnd.gif        }

 47InBlock.gif        string content = "";
 48InBlock.gif        public string Content
 49ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 50InBlock.gif            get
 51ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 52InBlock.gif                return content;
 53ExpandedSubBlockEnd.gif            }

 54InBlock.gif            set
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 56InBlock.gif                content = value;
 57ExpandedSubBlockEnd.gif            }

 58ExpandedSubBlockEnd.gif        }

 59InBlock.gif        public void Add(IThread thread)
 60ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 61InBlock.gif            list.Add(thread);
 62ExpandedSubBlockEnd.gif        }

 63InBlock.gif        public void Remove(IThread thread)
 64ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 65InBlock.gif            list.Remove(thread);
 66ExpandedSubBlockEnd.gif        }

 67InBlock.gif        public abstract void RenderContent();
 68ExpandedSubBlockEnd.gif    }

 69ExpandedBlockEnd.gif}

 70None.gif
 71None.gif
 72None.gifusing System;
 73None.gifusing System.Collections.Generic;
 74None.gifusing System.Text;
 75None.gif
 76None.gifnamespace CompositeStudy
 77ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 78InBlock.gif    public class Thread : AbstractThread
 79ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 80InBlock.gif       
 81InBlock.gif        public override void RenderContent()
 82ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 83InBlock.gif            //输出自己的Contetn
 84InBlock.gif            Console.WriteLine("Thread:"+this.Content);
 85InBlock.gif            foreach (IThread t in Children)
 86ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 87InBlock.gif                t.RenderContent();
 88ExpandedSubBlockEnd.gif            }

 89ExpandedSubBlockEnd.gif        }

 90ExpandedSubBlockEnd.gif    }

 91ExpandedBlockEnd.gif}

 92None.gif
 93None.gif
 94None.gifusing System;
 95None.gifusing System.Collections.Generic;
 96None.gifusing System.Text;
 97None.gif
 98None.gifnamespace CompositeStudy
 99ExpandedBlockStart.gifContractedBlock.gifdot.gif{
100InBlock.gif    public class Message:AbstractThread
101ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
102InBlock.gif        public override void RenderContent()
103ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
104InBlock.gif            Console.WriteLine("Message:" + this.Content);
105InBlock.gif            foreach (IThread t in Children)
106ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
107InBlock.gif                t.RenderContent();
108ExpandedSubBlockEnd.gif            }

109ExpandedSubBlockEnd.gif        }

110InBlock.gif
111ExpandedSubBlockEnd.gif    }

112ExpandedBlockEnd.gif}

113None.gif
114None.gif

工厂类为:
 1 None.gif using  System;
 2 None.gif using  System.Collections.Generic;
 3 None.gif using  System.Text;
 4 None.gif using  System.Data;
 5 None.gif
 6 None.gif namespace  CompositeStudy
 7 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 8ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 9InBlock.gif    /// 工厂类
10InBlock.gif    /// </summary>
11ExpandedSubBlockEnd.gif    /// <remarks>工厂类</remarks>

12InBlock.gif    public class ThreadFactory
13ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
14InBlock.gif        DataTable table = new DataTable();
15InBlock.gif        public ThreadFactory()
16ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
17InBlock.gif            table.Columns.Add("content");
18InBlock.gif            table.Columns.Add("IsTop");
19InBlock.gif            table.Columns.Add("IsMessage");
20InBlock.gif            table.Columns.Add("ID");
21InBlock.gif            table.Columns.Add("ParentID");
22InBlock.gif
23InBlock.gif            DataRow row = table.NewRow();
24InBlock.gif            row["content"] = "test";
25InBlock.gif            row["IsTop"] = false;            
26InBlock.gif            row["IsMessage"] = false;
27InBlock.gif            row["ID"] = 1;
28InBlock.gif            row["ParentID"] = 0;
29InBlock.gif            table.Rows.Add(row);
30InBlock.gif
31InBlock.gif            row = table.NewRow();
32InBlock.gif            row["content"] = "test1";
33InBlock.gif            row["IsTop"] = true;
34InBlock.gif            row["IsMessage"] = false;
35InBlock.gif            row["ID"] = 0;
36InBlock.gif            row["ParentID"] = -1;
37InBlock.gif            table.Rows.Add(row);
38InBlock.gif
39InBlock.gif            row = table.NewRow();
40InBlock.gif            row["content"] = "test2";
41InBlock.gif            row["IsTop"] = false;
42InBlock.gif            row["IsMessage"] = true;
43InBlock.gif            row["ID"] = 2;
44InBlock.gif            row["ParentID"] = 0;
45InBlock.gif            table.Rows.Add(row);
46InBlock.gif
47InBlock.gif            row = table.NewRow();
48InBlock.gif            row["content"] = "test3";
49InBlock.gif            row["IsTop"] = false;
50InBlock.gif            row["IsMessage"] = true;
51InBlock.gif            row["ID"] = 3;
52InBlock.gif            row["ParentID"] = 0;
53InBlock.gif            table.Rows.Add(row);
54ExpandedSubBlockEnd.gif        }

55InBlock.gif        public List<IThread> GetTopThreads()
56ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
57InBlock.gif            List<IThread> list = new List<IThread>();
58InBlock.gif            DataRow[] rows = table.Select("IsTop = true");
59InBlock.gif            foreach (DataRow row in rows)
60ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
61InBlock.gif                Thread t = new Thread();
62InBlock.gif                t.Content = row["content"].ToString();
63InBlock.gif                t.IsTop = true;
64InBlock.gif                DataRow[] cs = table.Select("ParentID="+Convert.ToInt32(row["ID"]));
65InBlock.gif                foreach (DataRow r in cs)
66ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
67InBlock.gif                    if (Convert.ToBoolean(r["IsMessage"]))
68ExpandedSubBlockStart.gifContractedSubBlock.gif                    dot.gif{
69InBlock.gif                        Message m = new Message();
70InBlock.gif                        m.Content = r["content"].ToString();
71InBlock.gif                        m.IsTop = false;
72InBlock.gif                        t.Add(m);
73ExpandedSubBlockEnd.gif                    }

74InBlock.gif                    else
75ExpandedSubBlockStart.gifContractedSubBlock.gif                    dot.gif{
76InBlock.gif                        Thread tt = new Thread();
77InBlock.gif                        tt.Content = r["content"].ToString();
78InBlock.gif                        tt.IsTop = false;
79InBlock.gif                        t.Add(tt);
80ExpandedSubBlockEnd.gif                    }

81ExpandedSubBlockEnd.gif                }

82InBlock.gif                list.Add(t);
83ExpandedSubBlockEnd.gif            }

84InBlock.gif            return list;
85ExpandedSubBlockEnd.gif        }

86ExpandedSubBlockEnd.gif    }

87ExpandedBlockEnd.gif}

88 None.gif

客户端调用方法为:
 1 None.gif using  System;
 2 None.gif using  System.Collections.Generic;
 3 None.gif using  System.Text;
 4 None.gif
 5 None.gif namespace  CompositeStudy
 6 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 7InBlock.gif    class Program
 8ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 9InBlock.gif        static void Main(string[] args)
10ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
11InBlock.gif            ThreadFactory factory = new ThreadFactory();
12InBlock.gif            List<IThread> threads = factory.GetTopThreads();
13InBlock.gif            foreach(IThread t in threads)
14ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
15InBlock.gif                t.RenderContent();
16ExpandedSubBlockEnd.gif            }

17InBlock.gif            Console.Read();
18ExpandedSubBlockEnd.gif        }

19ExpandedSubBlockEnd.gif    }

20ExpandedBlockEnd.gif}

21 None.gif

类关系图:

输结果为:
通过该事例的调用,就可以知道,组合模式的好处有:

1)         使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。

2)       更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利!

转载于:https://www.cnblogs.com/erichzhou/archive/2007/03/29/693073.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值