单一职责原则的核心是按变更动因而非功能数量划分职责:类应因同一原因被修改,命名需明确体现其唯一职责,方法归属须遵循“同改同存、异改异处”,并通过接口依赖注入确保职责隔离。

在大型 Java 项目中,用单一职责原则规划类与方法归属,核心不是“怎么分”,而是“为什么分”——所有拆分动作,都应围绕“谁会因为什么理由改它”来判断。一个类一旦被多个不相关的变更动因牵扯,就该切开。
看变化动因,而不是看功能数量
别数一个类有 3 个还是 8 个方法,重点看这些方法是否会被不同原因触发修改:
- 用户邮箱格式规则调整 → 只该动校验逻辑,不影响数据库保存或消息通知
- 从 MySQL 切到 PostgreSQL → 只该动数据访问层,业务逻辑和校验不该重编译
- 导出报表从 Excel 改成 PDF → 只该换导出实现,不影响订单创建、库存扣减等主流程
按角色建类,不用“Manager”“Helper”这类模糊命名
类名要能一句话说清它“做什么”,且主谓宾完整。含糊名字是职责不清的早期信号:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- ❌ UserManager → 不知道管状态?管权限?管通知?
- ✅ UserRegistrationService → 专做注册流程编排
- ✅ UserEmailValidator → 只校验邮箱格式与唯一性
- ✅ UserProfileRepository → 只封装对用户资料的增删改查和事务边界
方法归属:同改同存,异改异处
一个类里所有 public 方法,最好操作同一组字段、响应同一类事件、被同一类调用方使用:
- 如果
updatePassword()和sendWelcomeEmail()都写在UserServiceImpl里,但前者改密码加密算法,后者换邮件服务商——它们不该共处一室 - 如果某个方法只读
orderItems,另一个只写statusLog,说明状态域已分裂,该按数据上下文拆 - 测试时发现要 mock RedisTemplate、RestTemplate、JdbcTemplate 才能跑通一个类的单元测试 → 职责已混杂,必须拆
用接口+构造器注入守住职责边界
拆完类只是第一步;若新类仍直接 new 实现类、或静态调用工具方法,那职责只是“表面分离”:
- 所有依赖必须通过构造函数传入,类型为 interface(如
EmailSender,而非SmtpEmailSender) -
OrderPlacementUseCase类里,只持OrderValidator、InventoryClient、PaymentGateway三个接口,不碰具体实现 - 每个被依赖类可独立测试:比如
UserEmailValidator测试不需启动数据库,也不依赖真实邮件服务
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










