C#设计模式——组合模式(Composite Pattern)

[来源] 达内    [编辑] 达内   [时间]2012-11-12

在软件开发中,我们往往会遇上类似树形结构的对象体系。即某一对象既可能在树形结构中作为叶节点存在,也可能作为分支节点存在

一、概述

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); "> 在软件开发中,我们往往会遇上类似树形结构的对象体系。即某一对象既可能在树形结构中作为叶节点存在 也可能作为分支节点存在。比如在文件系统中,文件是作为叶节点存在,而文件夹就是分支节点。在设计这类对象时,如果将叶节点和分支节点区别对待,那么在实际开发中会带来较大的复杂性。比如客户端调用时可能会频繁的使用转型操作,同时代码的可维护性和扩展性也较差。在设计中使用组合模式可以解决这一系列弊端。

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">二、组合模式

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); "> 组合模式定义了叶节点和分支节点的一致的接口,将客户端代码与复杂的对象结构解耦,大大降低了客户端调用的复杂性。其结构图如下:

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">

< p align="left" style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); "> Component定义了所有对象的共同接口,可以在Component中定义管理Component组件的接口以保证一致性,也可以将管理接口下放至Composite中以提高系统调用的安全性。

< p align="left" style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">Leaf表示叶节点。

< p align="left" style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">Composite定义了分支节点对象的行为,并提供一个容器用户存储其子节点。

< p align="left" style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">Client通过Component来处理所有对象。

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">三、示例

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); "> 我们利用组合模式来实现一个绘图系统。在该系统中具有Line、Circle、Picture等多种元素,其中Picture可以含有各类子元素。

< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">首先定义Component。

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 1
     public abstract
 

class Graphic  2
     {  3
         private

 string _name; 
 4
 
 5         public
 Graphic(string name) 
 6

         {  7
             _name = name;  8
         } 

 9
 
10         public
 abstract void
 Add(Graphic graphic); 

11         public
 abstract void
 Remove(Graphic graphic); 

12
 
13         public
 virtual void
 Draw() 

14         { 
15             Console.WriteLine("
Draw {0} {1}

", GetType().Name, _name); 
16         } 
17     }
< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">接着定义Picture对象。

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 1
     public class


 Picture : Graphic  2     { 
 3         private
 List<Graphic> _graphic = new List<Graphic>(); 
 4

         public Picture(string
 name)  5
             : base

(name)  6
         { 

 7         } 
 8
 
 9         public
 override void
 Add(Graphic graphic) 

10         { 
11             _graphic.Add(graphic); 
12

         } 13
         public override
 void

 Remove(Graphic graphic) 14
         { 15
             _graphic.Remove(graphic); 

16         } 
17
         
18         public
 override void
 Draw() 

19         { 
20             base
.Draw(); 

21             foreach
 (Graphic graphic in _graphic) 
22

             { 23
 

                graphic.Draw(); 24             } 
25         } 


26     }
< p align="left" style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">再定义Line和Circle。

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 1
     public class


 Line : Graphic  2     { 
 3         public
 Line(string

 name)  4
             : base(name) 
 5

         {  6
 

        }  7
 
 8         public
 override void
 Add(Graphic graphic) 

 9         { 
10             throw
 new

 Exception("Line can't add graphic
"); 
11

         } 12
         public override
 void

 Remove(Graphic graphic) 13
 

        { 14             throw
 new Exception("


Line can't remove graphic"); 
15         } 
16

     } 17
 
18     public
 class Circle : Graphic 
19

     { 20
         public Circle(string
 name) 

21             : base
(name) 22
         { 

23         } 
24

 
25         public
 override void
 Add(Graphic graphic) 

26         { 
27             throw
 new

 Exception("Circle can't add graphic
"); 
28

         } 29
         public override
 void

 Remove(Graphic graphic) 30
 

        { 31             throw
 new Exception("


Circle can't remove graphic"); 
32         } 
33     }
< p style="margin: 10px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245); ">这样就可以通过统一的Draw 接口画出整幅图画。

资源下载