本文总结一下今天学习的Composite(组合)模式。内容主要基于李建忠WebCast《C#面向对象设计模式纵横谈》。
首先,看一下Composite模式的意图:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。――GOF 《设计模式》
  我们看这们个例子:我们有两类盒子,设为A类和B类,A类盒子的内部还装有盒子,而B类盒子内部不能装盒子,A类盒内部装的盒子既可以是A类的也可以是B类的,假设现在桌子上放有许多盒子(可能是A类或B类盒子),要求计算桌子上的总盒子数,如果是A类盒子,则需要算上它内部的盒子数,比如桌上有1个A类盒子box1和1个B类盒子box2,A类盒子内有1个B类盒子box3和1个A类盒子box4,这个box4内又装有3个B类盒子box5,box6,box7,那么总盒子数就是7。

  那现在要怎么做呢?A、B两类盒子都是盒子,那我们就定义一个盒子接口,GetBoxCount()方法将返回此盒子内的所有盒子数。

Design Patterns之Composite Pattern总结public interface IBox
}

然后是A类和B类盒子:
}

然后就可以在Main()方法中测试了:
Design Patterns之Composite Pattern总结public static void Main(string[] args)
}

我们可以得到结果:Total:6
可以看到,虽然A类和B类是不同的盒子,但客户程序却可以不去理会盒子内部还有没有装盒子,装的是什么盒子,只要简简单单地调用GetBoxCount()方法。这样的话,客户程序就可以跟A类盒子(内部可以再装盒子)的内部结构解耦。BoxContainer类就是Composite模式中的组合类,它内部可以再装有盒子。
同时注意到BoxContainer类的私有成员boxes是被声明为List,而不是注释中的List,虽然本例中声明为List也可以,但是当B类盒子不只一种时就不行了,声明为List也体现了面向对象程序设计中依赖抽象而不是依赖实现的思想。
上面的Composite模式叫安全的Composite模式(为什么叫安全的?在段尾见答案),因为对于SingleBox来说,内部不能装盒子,所以没有Add和Remove方法,而BoxContainer有,但这种模式却导致了SingleBox和BoxContainer的接口不一致。还有一种Composite模式叫透明的Composite模式,它把Add和Remove等这些操作子对象的方法定义在IBox接口中,这样接口就一致了(比如在Main方法中就都可以用IBox来声明一个BoxContainer了:IBox boxContainer1 = new BoxContainer();),但是SingleBox里用Add和Remove明显是不行的,所以,在SingleBox的Add和Remove方法中都抛出一个异常,而在安全的Composite模式中是没有这个问题的,所以才叫安全的Composite模式。在实际应用中选择哪种Composite模式,要根据具体情况来看,其实也就是权衡安全性和透明性的问题了。

总 结:
1. Composite(组合)模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。
2. 有安全型的Composite模式和透明型的Composite模式,在它们中做选择也就是在安全性和透明性中找个平衡点。

相关文章: