高内聚低耦合继承的核心是仅在严格 is-a 关系且不破坏父类契约时才继承,否则优先组合+接口;抽象类须精简稳定、职责单一;接口应小而专;依赖必须显式可控。

Java 中设计高内聚低耦合的继承结构,核心不是“要不要继承”,而是“什么情况下才值得继承”——必须满足明确的 is-a 关系,且子类不破坏父类契约。滥用继承是耦合的源头,多数场景该用组合+接口替代。
只在真正存在“is-a”语义时才用继承
比如 Apple extends Fruit 合理,因为苹果天然是一种水果;但 OrderService extends RedisHelper 或 PaymentProcessor extends HttpClient 就违背语义——它们不是“是一种”,只是“用到了”。这类关系强行继承,会导致子类被父类实现细节绑架,一改全崩。
- 判断标准:把子类名替换成“是一种 + 父类名”,读起来自然且逻辑成立
- 反例:
UserService extends DateUtils—— “用户服务是一种日期工具”?显然不成立 - 替代方案:把日期处理抽成
DateFormatter,在UserService中作为private final字段持有
抽象类要精简、稳定,避免塞满业务逻辑
抽象类不是“通用功能仓库”。它应只定义子类共有的骨架行为(如模板方法),且方法粒度细、职责单一。一旦抽象类里出现 if (type == "wechat") 或混入发短信、写日志、查数据库等无关能力,就已偏离初衷。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 抽象方法命名需体现契约,如
doValidate()、buildRequest(),而非笼统的process() - 钩子方法(hook)必须是
protected且提供空实现,子类按需重写,不强制 - 禁止在抽象类中直接 new 具体实现类或硬编码配置值
优先用接口定义能力,而非用继承传递行为
当多个类需要“具备某种能力”,但彼此没有父子关系时(比如 Car、Bike、Drone 都能 move()),应定义 Movable 接口,各自实现。这样既解耦,又支持一个类实现多个能力(如 Car implements Movable, Insurable)。
- 接口方法必须语义清晰、无分支逻辑、IO 稳定(比如不随参数类型爆炸式增长)
- 避免“大而全”的接口,如
OrderService接口里同时定义创建、查询、导出、通知、对账——这实际是多个职责的拼凑 - 每个接口聚焦一件事,例如
OrderCreator、OrderNotifier、OrderExporter
构造与依赖必须显式、可控、不越界
继承结构里的类,依然要遵守依赖注入原则。子类不能绕过父类封装,偷偷访问底层资源;父类也不能在构造中强依赖子类未提供的具体实现。
- 父类构造函数只接收其自身所需依赖,不预留“给子类用”的空白字段
- 子类通过构造器将依赖传给父类,或由外部容器统一注入,而非自己 new 或调静态单例
- 禁止父类方法返回
new ArrayList()这类具体类型——应返回List>,让调用方决定实现
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










