面向对象设计模式之Composite组合模式(结构型)

说明动机:
 * 在面向对象系统中,我们常常会遇到一类具有“容器”特征的对象——即他们在充当对象的同时
 * ,又是其他对象的容器。例如:
 * public class SingleBox:IBox      public class ContainerBox:IBox
 * {                                {
 *   public void Process(){....}        public void Process(){....}
 * }                                                 public ArrayList GetBoxes(){....}
 *                                   }
 * 如何我们要对这样的对象容器进行处理:
 * IBox box=Factory.GetBox();
 * if(box is ContainerBOx)
 * {box.Process();ArrayList list=((ContainerBox)box).GetBoxes();...//将面临比较复杂的递归处理}
 * else if(box is SingleBox){box.Process();}
 * 这样的处理过程显然将其类结构过多的暴露给客户,而且让客户的代码依赖于对象容器复杂的内部实现结构;
 * 对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等
 * 弊端。如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客
 * 户代码就像处理简单对象一样来处理复杂的对象容器

意图:将对象组合成树形结构以表示“部分”与“整体”的层次结构。组合模式是使得用户 对单个对象和组合对象的使用一致性。

可适用性:

  • 你想表示对象的部分-整体层次结构。
  • 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

UML图解:

示例代码:

  1 namespace Composite  //示例代码
  2 {
  3     /// <summary>
  4     /// 树容器对象接口
  5     /// </summary>
  6     public abstract class  IBox
  7     {
  8       
  9         public abstract void Process();
 10         public abstract void Add(IBox box);
 11         public abstract void Remove(IBox box);
 12         public abstract IBox GetChild(int index);
 13     }
 14 
 15     /// <summary>
 16     /// 单个容器(里面没有子容器)
 17     /// </summary>
 18     public class SingleBox : IBox
 19     {
 20 
 21         public override void Process()
 22         {
 23             //do something processing...
 24             
 25         }
 26 
 27         public override void Add(IBox box)
 28         {
 29             throw new NotSupportedException();
 30         }
 31 
 32         public override void Remove(IBox box)
 33         {
 34             throw new NotSupportedException();
 35         }
 36 
 37         public override IBox GetChild(int index)
 38         {
 39             return this;
 40         }
 41     }
 42 
 43     /// <summary>
 44     /// 容器(有子容器)
 45     /// </summary>
 46     public class ContainerBox : IBox
 47     {
 48         ArrayList boxList = null;
 49 
 50         public override void Process()
 51         {
 52             //do process for myself。。
 53             //......
 54             //do process for the box in boxList
 55             foreach (IBox item in boxList)
 56             {
 57                 item.Process();
 58             }
 59         }
 60 
 61         public override void Add(IBox box)
 62         {
 63             if (boxList == null)
 64             {
 65                 boxList = new ArrayList();
 66             }
 67             boxList.Add(box);
 68         }
 69 
 70         public override void Remove(IBox box)
 71         {
 72             boxList.Remove(box);
 73         }
 74 
 75         public override IBox GetChild(int index)
 76         {
 77             if (boxList == null)
 78             {
 79                 throw new  NullReferenceException();
 80             }
 81             else if (index < 0 || index > boxList.Count)
 82             {
 83                 throw new ArgumentOutOfRangeException();
 84             }
 85             return (IBox)boxList[index];
 86         }
 87     }
 88 
 89     public class App
 90     {
 91         public static void Main()
 92         {
 93             IBox box = new ContainerBox();
 94             box.Add(new SingleBox());
 95             box.Add(new ContainerBox());
 96 
 97             box.Process();//这样客户只需调用Process()方法就足够处理每个子容器了
 98         }
 99     }
100 
101    }


Composite模式的几个要点 :

1、Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系   转化为“一对一”的关系,使得客户代码可以一致地处理对象和对象容器,无需关系处理      的是单个对象,还是组合的对象容器。    

 2、将“客户代码与复杂的对象容器结构”解耦是Composite模式的核心思想,解耦之后,客户代码     * 将于纯粹的抽象接口——而非对象容器的复杂内部实现结构——发生依赖关系,从而更能“应对变化”   

3、Composite模式中,是将Add和Remove等和对象容器相关的方法定义在了表示抽象对象的Component类中  ,还是将其定义在表示对象容器的Composite类中,是一个关乎透明性和安全性的两难问题,需要仔细权衡   。这里有可能违背面向对象的“单一职责原则”,但是对于这种特殊结构,这又是必须付出的代价。ASP.NET  控件的实现在这方面为我们提供了一个很好的示范。 

 4、Composite模式在具体实现中,可以让父对象中的子对象反向追溯;如果父对象有频繁的遍历要求,可使用缓存技巧改善效率

注:本示例代码是本人学习Webcast C#面向对象设计模式纵横谈系列讲座视频时,跟着李建忠老师一步一步的编写的,在此奉献出来,仅供大家参考

作者:JumpByte
来源:http://www.cnblogs.com/yja9010
更新: http://jumpbyte.cn
声明:本博客原创文字只代表本人的观点或结论,于网站他人无关,非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
原文地址:https://www.cnblogs.com/yja9010/p/3178772.html