如何理解 少用继承,多用组合
HeadFirst 设计模式一书中,开篇就提到了这个有趣的点:
当我们想让鸭子能飞的时候,首先跳出来的想法是给鸭子类增加一个fly()方法,然后所有的子类直接继承完事;
结果,有一个橡皮鸭类也继承了,导致了我们不想看见橡皮鸭满天飞的后果;这里显然是有问题的,然后我们在想,橡皮鸭类中直接override这个方法,实现为空不就行了吗;看着是解决了问题,但是,如果后面不断有新的类来继承鸭子类,为每个新增的类我们都要检查fly() 方法,quack()方法等;或者当想要新增特性时,要检查每个子类的对应行为是否需要override掉;
一个进阶的想法是:
这样的话,每个类显式的声明自己是否继承Flyable接口,或者Quackable接口,来保证自己的行为不会偏离预期;但是其实,为了解决一小部分的问题,带来了更多的重复代码。
推荐的做法是:
这么做的好处是,鸭子的行为不再是继承而来的,而是组合实现的;组合的优势在于,可以在运行时动态地改变行为;
继承的问题在于,我们过于依赖实现,也就是父类有这个方法的实现,我们只能选择默认,或者覆盖;
不符合一条重要的设计原则:针对接口编程,而不是针对实现编程;