设计模式 (8) - Composite模式

来源:互联网 发布:淘宝卖什么最赚钱排行 编辑:程序博客网 时间:2024/05/16 15:58

问题描述

程序有时候需要同时处理叶子节点对象及其容器对象。普遍的做法是:程序依据对象类型调用不同的方法来实现逻辑控制。这种方法区别对待容器对象和节点对象,让代码显得复杂臃肿。Composite模式让容器对象和节点对象提供一致的接口,从而对客户隐藏对象类型的差异性。

Composite模式

如图所示,Component接口定义了节点对象(即Leaf)和容器对象(即Composite)的公共接口。Composite对象把Operation()操作递归的运用到它的儿子节点(可能是Leaf对象,也可能是Composite对象)上去。客户通过一致的接口Component来访问Leaf对象和Composite对象,几乎不关注这两种对象的差异性,从而简化了客户逻辑。客户代码基于统一接口Component来实现,即使添加新的Leaf或者Composite类,客户代码也不需要修改。


下图展示了Android代码中使用Composite模式的一个例子:


讨论

Composite模式的价值在于:客户使用一致的方法来调用Leaf对象和Composite对象的方法。但是对于Composite对象管理子部件的接口,例如Add()/Remove()/GetChild()等操作的定义需要作出取舍:

  • 把这些管理接口定义在Component接口中,有利于提高客户端的透明性。Leaf对象的Add()操作直接释放参数对象(但是客户逻辑可能并不希望如此);Remove()操作直接失败(但是客户可能希望释放该Component对象);GetChild()直接返回空指针等。
  • 把这些管理接口定义在Composite接口中,有利于提高类型安全性。因为C++编译器可以防止Leaf对象上调用Add()/Remove()/GetChild()等接口,毕竟这些接口对于Leaf对象的逻辑意义总是牵强的。

Composite模式更加强调对于客户端的透明性。为了实现这种透明性,Add()/Remove()等接口必须定义在Component接口上。考虑到Add()/Remove()等操作即使对于Composite对象也有失败的可能,那么我们可以限定Add()/Remove()等接口的返回值语义:当返回FALSE的时候,客户软件需要正确的处理参数对象。从安全编程的角度看,客户软件这样处理是值得的,同时也保证了客户软件对于Leaf对象和Composite对象处理的一致性。

0 0
原创粉丝点击