面向对象设计实践指南 8 - 组合对象

组合 composition 定义的中心思想是:自行车不仅有多个零件,它还要通过接口与它们进行通信。零件是一个角色,自行车愿意与任何扮演这个角色的对象进行合作。

继承和组合的抉择

  • 经典继承中,对象被组织成类关系,以便消息可以自动委托调用正确的行为。消息委托是免费的。
  • 组合里,对象之间的关系没有体现在类层次结构里,对象独立存在,需要显式地进行消息委托。

一般的规则是,如果能用组合解决尽量使用组合,因为组合比继承包含了更少的内建依赖关系。

继承的优劣

代码应该满足透明、合理、可用和典范四点要求。

利,建模正确的时候。

  • 合理性:继承结构顶部附近的方法有着广泛的影响,行为上的大变化可以通过代码的小改动来实现。
  • 可用性:继承的代码可以用 开闭 原则来描述,对扩展保持开放,对修改保持关闭。添加新子类不需要修改已有代码。
  • 典范性:易于扩展,提现了抽象,现有的模式很容易遵从,为编写扩展代码提供了指导。

弊,建模不正确或将继承应用到一个不适合的问题。

  • 合理性的反面:在错误建模的层次结构的顶层附近,更改所带来的成本极高。
  • 可用性的反面:当新子类表示的是混合类型时,很难实现行为的添加。试图将两个子类的特点结合成一个新的单一对象。

组合的优劣

  • 自然趋势是创建出需要包含简单责任的小对象,它们可通过明确定义的接口进行访问。
  • 这些小对象都有单一职责,并且特定了自己的行为。均具有透明性:代码易于理解,如有变化发生,所带来的影响也很明显。
  • 当更改层次结构中位于它之上的类,也不会产生副作用。
  • 在新的意想不到的环境里,组合更易于扩展,且对变化有更高的容忍度。

  • 尽管每个小部分都很容易理解,但组合后的对象可能未必如此。
  • 组合对象必须明确的知道哪条消息需要委托给谁。

选择关系

“是什么” 和 “有什么” 的区别,是决定继承和组合的核心问题。一个对象的部分越多,它越有可能使用组合来建模。

  1. 将继承用于 “是什么” 关系
  2. 将鸭子类型用于 “表现得像什么” 关系
  3. 将组合用于 “有什么” 关系

小结

  • 组合后的对象往往由简单、离散的实体组成,它们可以轻易地重新排列成新的组合
  • 这些简单的对象易于理解、重用和测试
  • 组合、经典继承和通过模块的行为共享,都是互相对立的代码编排技术

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @Victor Jan 13, 2015

奉献爱心