组合模式
组合模式允许开发者将对象组合成树状结构以表示部分-整体层次结构。组合能让客户端统一对待单个对象和对象组合。
示例
最常见的组合模式例子莫过于文件-文件夹系统。文件夹可以包含文件和其他文件夹,而文件夹本身也是一种文件。这种层次结构与组合模式完全吻合。
结构
组合模式示意图
组合模式中,客户端仅直接与高层接口组件交互,而组件则可以是叶节点(单个对象)或容器(包含其他组件的对象)。组件接口定义了对于叶节点和容器的通用操作。
备注
一个值得思考的点是容器中的添加与删除操作是否应当在组件接口中定义。
如果定义在接口中,那么所有组件都需要实现这两个方法,但对于叶节点来说,这两个方法是没有意义的。这会违反接口隔离原则,但同时也使得客户端可以完全统一对待叶节点和容器。
如果只在容器中定义这两个方法,那么客户端在需要对叶节点进行添加和删除操作时,就需要进行类型检查。这在一定程度上违反了依赖倒置原则,但同时也使得接口更加清晰。
应用场景
- 当需要实现树状对象结构,且对于叶节点和容器有相同的操作时
优缺点
优点
- 利用多态和递归机制更方便地处理复杂树结构。
- 开闭原则:无需更改现有代码,你就可以在应用中添加新元素,使其成为对象树的一部分。
缺点
- 当组件功能差异较大时,强行统一接口可能会适得其反
代码示例
下面的代码示例展示了组合模式的实现。Graphic
是一个组件接口,定义了简单对象(叶节点)和复杂对象(容器)的通用操作。Dot
是一个叶节点类,代表一个简单的图形。CompositeGraphic
是一个容器类,可以包含其他 Graphic
对象(包括 Dot
和其他 CompositeGraphic
)。客户端代码可以通过 Graphic
接口统一处理这些对象,而无需关心它们是简单对象还是组合对象。