应严格控制继承深度(≤2层),优先用组合、接口和策略模式替代“为复用而继承”,确保继承仅表达真实业务中的“is-a”关系,避免上帝类与抽象失焦。

继承链过长会让类变得难以理解、修改和测试,基类一旦变动,下游所有子类都可能意外崩溃——这不是设计复用,而是风险传递。关键不是少用继承,而是让继承真正服务于明确的抽象意图。
用组合替代“为复用而继承”
当子类只是想用父类的功能,而不是“是一种”父类时,继承就错了。比如一个ReportGenerator类不需要继承DatabaseConnection,它只需要持有连接实例。
- 把可复用的行为封装成独立类或工具函数,通过字段注入或方法参数传入
- 使用接口定义能力契约(如DataFetcher、Formatter),让具体实现自由替换
- 避免“模板方法模式”滥用——若钩子方法超过3个,或子类重写逻辑高度相似,说明抽象粒度太细
拆分基类:按职责收敛,而非按层级堆叠
一个叫BaseService的类如果同时处理权限校验、缓存、日志、事务、重试,它已经不是基类,而是反模式的“上帝类”。
- 识别基类中实际被子类共同依赖的最小行为集,保留为真正通用的抽象(如TransactionalOperation)
- 将非强制、可选的能力(如缓存策略、审计日志)抽成装饰器或策略对象,由子类按需装配
- 删除空实现的钩子方法;如果某个子类从不重写某方法,说明它不该在基类中
限制继承深度,强制审查向上依赖
超过三层继承(A ← B ← C ← D)通常意味着抽象失焦。每增加一层,变更影响面指数级扩大。
- 在代码规范中明确继承深度上限(建议≤2),CI阶段可用静态分析工具自动拦截超限提交
- 每次新增子类前,先问:它是否必须继承当前父类?能否直接实现接口 + 组合已有组件?
- 对现有深继承链做“断层评估”:找出中间层中未被下游使用的字段/方法,将其上移或下放,缩短路径
用领域建模驱动继承设计,而非技术便利
继承关系应反映真实业务中的“is-a”语义,而不是为了少写几行代码。客户是人,VIP客户也是人,但“定时任务调度器”不是“人”的一种。
- 画出领域概念图,只对有明确泛化关系的实体建模继承(如Payment → CreditCardPayment、BankTransferPayment)
- 当出现“既是A又是B”(如一个对象既要可缓存又要可序列化),优先用接口实现多重能力,而非多继承或混合基类
- 定期重构:把长期未新增子类的抽象类改为具体类+策略,把久未被重写的模板方法内联到子类
继承不是万能胶,而是手术刀——只在解剖清晰、边界确定的地方下刀。结构轻了,代码才真正强壮。










