继承改组合需先明确目标,识别深层链、伪is-a、父类职责混乱三类坏味道;用工具提取共用行为生成组件并代理接口;分步过渡保持兼容;最后靠测试验证行为不变与注入配置正确。

直接把继承结构改成组合,不是删掉父类、加个字段就完事。关键在于识别职责边界、保留行为语义、确保调用兼容——自动化工具能帮你做大量机械工作,但前提是你得告诉它“哪些该拆、怎么连、哪里要保留接口”。
明确重构目标:先判断是否真需要改继承
不是所有继承都该被替换。重点处理以下三类典型坏味道:
- 深层继承链(比如 A → B → C → D),每次新增功能都要改多层,容易误伤
-
“伪is-a”关系,例如
AdminUser继承User,但只为了复用日志方法,实际语义上并不构成“是一种用户” -
父类塞满不相关逻辑,如
OrderService里混着支付、通知、库存校验,子类被迫继承全部
用工具识别并提取可组合单元
主流重构工具(如 Rector、JetBrains IDE 插件、PyCharm 的 Python Refactor)能自动扫描出可提取的共用行为:
PyCharm 2026.2是 JetBrains PyCharm 的指定版本安装包,下载地址指向官方 Windows 安装包直链,可用于旧项目兼容、版本回退和环境测试。
- 选中重复出现的字段+方法组合(如
log_action()+_logger实例变量),执行 Extract Class 或 Extract Component - 对父类中与核心领域无关的功能(如通用缓存、审计日志、序列化),生成独立组件类,并标注为
HasLogger、HasCache等能力接口 - 工具会自动生成委托方法(如
def log(self, msg): return self._logger.log(msg)),避免调用方代码断裂
保持向后兼容:用接口+委托过渡
别让下游立刻改调用。分两步走:
- 第一步:让原父类实现新定义的组合接口(如
LoggerProvider),内部仍用旧字段,但对外暴露标准方法 - 第二步:将子类中对父类方法的直接调用,逐步替换为通过组合对象访问(工具支持 Rename Symbol + Replace Inheritance with Composition 联动)
- 关键细节:保留原父类的 public 方法签名,仅改变内部实现;新组合类用
__getattr__(Python)或__call(PHP)做透明代理,降低迁移成本
验证与收尾:靠测试守住边界
重构不是改完就结束,而是靠测试确认没破坏行为:
- 运行原有单元测试,确保所有断言通过(这是组合重构成功的硬指标)
- 检查依赖注入容器配置——原来通过继承隐式获得的能力,现在需显式注册组合实例(如 Spring 的
@Autowired LoggerComponent) - 对新组合类单独补全测试:验证它能否被任意对象持有、替换、Mock,这才是组合真正带来的弹性










