高内聚低耦合的关键在于接口承载清晰职责边界、实现类专注单一责任且可替换;需满足单一语义、稳定io、无分支逻辑;依赖注入用构造器+final;按领域拆分高内聚类;包结构须反映分层职责。

用Java接口实现高内聚低耦合,关键不在“有没有接口”,而在于接口是否真实承载了清晰的职责边界,并让实现类只专注一件事、不越界、可替换。
接口不是摆设:必须定义契约,而非包装已有类
很多同学一说“解耦”就立刻加个 interface,然后把原 Service 类名后面加个 “Impl” 就完事。这没用——如果接口方法堆了 12 个,包含发短信、导出 Excel、校验身份证、调第三方物流,那这个接口本身就在制造高耦合。
真正有效的接口要满足三个条件:
-
单一语义:比如
OrderPaymentService只管“支付成功后更新订单状态并通知用户”,不掺杂库存扣减或积分发放 -
稳定输入输出:参数封装成 DTO(如
PayRequest),返回统一结果(如Result<payresponse></payresponse>),不暴露实体或数据库细节 -
无业务分支逻辑:接口里不能有
if (type.equals("alipay")),这类判断应交给上层编排或策略选择器
依赖注入要“看得见、换得动、测得了”
Spring 的 @Autowired 很方便,但容易掩盖问题。真正体现低耦合的是:你在测试时能不能一句话就换掉依赖?
推荐做法是构造器注入 + final 字段:
- Controller 中只持
private final UserService,不关心它背后是 MySQL 还是内存 Map - 单元测试里直接 new 一个
MockUserService()传进去,完全绕过数据库和网络 - 避免
static工具类调用、避免new XxxServiceImpl()、避免在类内部 new 任何外部服务实例
内聚靠拆,不是靠堆:每个类只守好自己的“一亩三分地”
高内聚不是“把所有相关代码塞进一个类”,而是“把真正属于同一责任的代码放一起,其他的一律请出去”。
常见重构动作包括:
- 把
UserServiceImpl.register()里邮箱校验、密码加密、发送欢迎邮件、初始化用户积分等逻辑,分别拆成EmailValidator、PasswordEncoder、WelcomeNotifier、PointInitializer - 删除
CommonUtils,按领域新建DateFormatter、JsonParser、IdGenerator,每个类只做一类事、方法不超过 5 个 - 发现某个方法需要传 6 个参数且类型各异,基本说明它不该属于当前类——把它抽成新服务,由调用方组装上下文后传入
包结构即架构图:目录层次要反映职责分层
包名不是命名习惯,是模块边界的显性表达。混乱的包结构会让解耦努力前功尽弃。
一个健康的 Spring Boot 包结构应类似:
-
controller:只处理 HTTP 协议层(接收参数、校验格式、返回 JSON),不碰业务规则 -
service:仅做业务流程编排(如“先扣库存→再创建订单→最后发消息”),不写 SQL、不操作 Redis -
repository:只和数据打交道(JPA 接口或 MyBatis Mapper),不包含 if/else 业务判断 -
domain:放核心模型(Order、Product)和值对象(Money、OrderId),不含任何框架注解 -
infrastructure:放适配器(如SmsGatewayAdapter、AlipayClientWrapper),用来把第三方 SDK 转成你定义的接口
只要包结构清晰,新增功能时就知道该往哪加、不该往哪改,自然就远离了“改一处崩一片”的窘境。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











