组合模式 -- Composite

2017-03-27 21:21:04   最后更新: 2017-03-27 21:21:04   访问数量:288




组合模式是将对象组合成树形结构,来表示“部分-整体”的层次结构,它使得用户对单个和组合对象的使用具有一致性

很多情况下,用户可以使用多个简单的组件组合成更大的组件,而这些简单的组件中,某个组件可能出现一次或多次,如果使用容器来存储出现多次的组件,那么系统就必须对容器还是组件进行区分和特殊的处理,因为用户需要的是组件的组合,而不需要容器

如下图所示,Composite 模式通过树形结构递归组合了一系列对象

 

 

 

 

如上图所示,Composite 模式由下列组件构成:

  1. Component -- 为组合中所有组件对象声明的抽象接口,在某些情况下,可以为共有接口提供缺省实现,拥有一个用来访问和管理子组件的接口
  2. Leaf -- 在组合中表示叶子节点,叶子节点没有子节点,所以只定义了对象的行为
  3. Composite -- 用于存储子部件的操作,实现与子部件有关的操作
  4. Client -- 通过 Component 接口操作组合部件的对象

 

Client 通过调用 Component 类接口与组合结构中的对象进行交互,如果接收者是一个叶子节点,则直接处理请求,否则如果是一个 Composite,那么就会递归地发给他的子部件进行处理

 

有时,子节点也会保存父节点的引用,从而让系统能够从子节点到父节点的遍历和管理变得很容易,福及诶单也因此可以很容易的简化结构或是上移、删除

如果允许子部件被多个父部件共享,将会节省很多空间,但是如果想要通过子节点上溯到他的父节点,这样的情况下显得有些不容易处理,另外,如果需要删除某个 Composite,那么共享的 Leaf 如何处理将会是一个较为复杂的问题

如果将 Leaf 看成是特殊的 Composite,那么在 Component 中就可以为全部的子节点提供默认操作了,这可能是一个很好的选择,leaf 只是没有子节点的 Composite,也很容易理解和构建,但这也意味着 Component 的公共操作中可能会存在对 Leaf 来说无意义的操作,如图中的 add 和 remove 操作,系统的安全性的考虑将必须对此作出必要的处理

由于 Component 是所有组件的父节点,因此如果在 Component 中维护一个所有对象引用的集合有时是十分方便的,但是这又会引入一定的复杂度和空间的浪费

如果需要考虑子节点的顺序,必须仔细设计子节点的访问和管理接口,在这个方面,结合 Iterator 模式可能是一个不错的选择

 

  1. Composite 模式定义了包含基本对象和组合对象的类层次结构,可以处理十分复杂的情况
  2. 客户端代码却十分简洁,他不需要关心处理请求的是一个节点还是多个节点的组合
  3. 由于组合是递归进行的,因此添加一个新的叶子会是非常简单的

 

事实上,此前我们介绍 nginx 源码时曾经介绍过这一模式:

HTTP 请求处理的 11 个阶段 -- ngx_http_handler

nginx http 请求处理的 11 个阶段中,每个阶段都有可能调用 0 个或多个回调函数,nginx 正是使用 Composite 模式的思想将他们组合成了一个树状结构

 






读书笔记      技术帖      数据结构      龙潭书斋            component      设计模式      模式      design pattern      composite      结构型模式      组合模式      组合     


京ICP备15018585号