继承缺陷以及替代方案
继承的好处
轻松实现代码复用
继承的缺陷
紧耦合
- 牵一发而动全身。父类的一个改动,会影响所有子类的行为
- 拔出萝卜带出泥。当在另外的项目里复用某个子类的代码时,要跟着把父类以及所有的相关依赖也复制过去
类爆炸
- 每当增加一个新feature时,继承体系中的类要翻倍。
究竟哪些场景适合用继承
- 层级关系明显,功能划分清晰。父类只是给子类提供基础服务,并不涉及子类的业务逻辑
Object并不影响Model, View, Controller的执行逻辑和业务 Object为子类提供基础服务,例如内存计数等
ApiManager并不影响其他的Manager
ApiManager只是给派生的Manager提供服务而已,ApiManager做的只会是份内的事,对于子类做的事情不参与。
- 父类的所有变化,都需要在子类中体现,也就是说此时耦合已经成为需求
Object对类的描述,对内存引用的计数方式等,都是普遍影响派生类的。 ApiManager中对于网络请求的发起,网络状态的判断,是所有派生类都需要的。 此时,牵一发动全身就已经成为了需求,是适用继承的
不满足以上特点的,慎用继承
继承的替代方案
- 子类只是使用相同的接口—>protocol
- 子类只是想在某些时机额外一些自定义的函数—>delegation(AOP中的消息拦截器啊, 以及策略模式中的strategy等都是这种机制)
- 子类只是给父类增加一些简单功能—>category
在用类别扩展一个不是你自己的类的时候,在方法前添加前缀是个比较好的习惯做法。
使用类别还有另外一个风险,那就是,到最后你可能会使用一大堆的类别,连你自己都会失去对代码全局的认识。假如那样的话,创建自定义的类可能更简单一些。 - 父类是抽象类(不能直接使用),子类提供一些属性配置项来完成对象的setup工作—>使用Configuration Objects
- 复用某些功能,而不必共享同样的接口—>组合。 组合是替代继承最强大有效的方案
当继承体系超过2层时,你就要好好考虑是否采用继承的方案了。