继承滥用的典型信号包括子类只调用父类部分逻辑、子类无需父类某能力、新增类型被迫加继承层却无真实“是一个”关系;应改用组合,将能力拆为可插拔组件(如filereader、filewriter),按需注入,保留继承仅用于共享骨架流程。

识别继承滥用的典型信号
当代码中出现以下情况,说明继承可能被误用了:子类重写父类方法但只调用 super 的一部分逻辑;某个子类完全不需要父类的某项能力(比如“内部订单”继承了“支付校验”,实际从不支付);新增业务类型时被迫加一层继承,但新类和已有类之间并不存在真实的“是一个”关系。这些不是小问题,是模型与代码开始脱节的明确提示。
把能力拆成可插拔的组件
不要让多个业务类都去继承一个大而全的基类。例如原有一个 FileService,混着读、写、删、权限校验逻辑。应改为定义接口或行为契约:FileReader、FileWriter、PermissionChecker。每个具体场景按需组合——管理员实例注入全部三个组件,只读用户只注入 FileReader 和轻量级 PermissionChecker。在 JavaScript 中,可用普通对象或类实现这些能力,再通过构造函数传入目标类。
用组合替代硬编码依赖
避免在类内部直接 new 某个策略类。把组件作为参数传入构造函数,例如:
- new OrderService(new VIPPriceCalculator(), new StubInventoryChecker()) —— 便于测试
- new OrderService(priceCalc, inventoryCheck) —— 支持运行时切换,比如灰度阶段按用户 ID 哈希选择新旧库存检查器
- 组件本身可独立单元测试,无需启动整个服务上下文
保留继承仅用于真正共享的骨架流程
不是彻底不用继承。如果多个类确实共用一套不可变的执行框架(比如统一的日志埋点入口、异常统一包装、事务开启与提交模板),可以保留一个抽象基类,但它只定义模板方法和钩子,不包含任何业务判断逻辑。所有具体的“要不要扣库存”“走哪个价格公式”等决策,全部交给组合进来的策略组件完成。这样骨架稳定,行为灵活,职责清晰。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











