组合优于继承,多用组合少用继承。
继承有三个主要作用: 表示类之间的 is-a 关系,支持多态,解决代码复用的问题。但继承层次过深、过复杂,也会影响到代码的可读性和可维护性(如中间的类改起来不方便)。
这三个作用都可以用组合关系,接口和委托模式来代替。并且能够解决上述问题。
但是,也会引入新的问题。继承改写成组合意味着要做更细粒度的类的拆分。这也就意味着,我们要定义更多的类和接口。
所以,如果类之间的继承结构稳定(不会轻易改变),继承层次比较浅,继承关系不复杂,我们就可以大胆地使用继承。反之,应尽量使用组合来替代继承。
此外,thinking in java 中说,我们用继承主要是为了用它的多态。代码复用是次要的,只为了代码复用而用继承后期会很难维护,还是用组合的好。
一个例子,前端框架React推荐类组件用HOC(高阶组件)来代替继承,就是用组合来代替继承。
也有一种观点: 无论什么时候都用组合,接口和委托来替代组合
- 人无法预知未来,现在比较稳定的类继承关系将来未必稳定。
- 两种设计之间的选择耗费资源,每次都要为这个问题拿捏一下,甚至争论一下,不如把争论放在业务逻辑的实现上。
- 相对于接口+组合+委托增加的复杂度,代码统一成接口+组合+委托带来的好处更多,利于阅读和交流,毕竟读代码的次数大于写的次数,读一种类型的代码的难度远低于读两种类型。
- 新的编程语言让接口+组合+委托变得容易,例如Kotlin就有专门的语法糖支持,消除了很多模板代码。
- 接口+组合+委托符合矢量化思想,那就是将物体特征分成不同的维度,每个维度独立变化。继承则是将物体分类,抽取共性,处理共性,操作的灵活性大打折扣,毕竟现实中的物体特征多,共性少。
- [OOP, design pattern]
