单一职责原则(srp)的核心是让每个类仅因一个变化原因被修改。应按变化维度(如日志格式、数据库切换、导出格式)而非功能名词拆分类,配合依赖注入和窄接口实现真正解耦,方法与模块级同样适用该原则。

设计“完美”的类不是追求代码行数最少或名字最短,而是让每个类只因一个理由被修改——这才是单一职责原则(SRP)落地的关键。
看变化,而不是看功能
别数一个类有几个方法,要问:“如果需求变了,哪些改动会逼你动这个类?”
- 日志格式调整 → 要改它?说明混了日志逻辑
- 数据库从 MySQL 换成 PostgreSQL → 要改它?说明数据访问和业务逻辑没分开
- 导出格式从 Excel 改成 PDF → 要改它?说明导出能力不该和核心业务绑在一起
按“谁会因为什么改”来拆分
拆类不是照着名词切(比如 User、Log、Excel),而是按变化维度切:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 数据模型类(如 User):只存字段、基础校验(邮箱格式)、getter/setter,不碰 I/O 或流程
- 数据访问类(如 UserRepository):只封装增删改查,换 ORM 或数据库时只动它
- 业务编排类(如 UserService):调用其他类完成注册、审核等流程,但不实现校验细节或发邮件逻辑
- 能力服务类(如 EmailService、FileExporter):专注一件事,可被多个业务复用
依赖注入是解耦的最后一步
光把类拆开还不够。如果 UserService 里直接 new EmailService(),那它还是“知道”怎么发邮件,职责没真正分离。
- 用构造器注入:UserService(UserRepository repo, EmailService emailer)
- 避免静态工具类或全局单例直接调用,它们会悄悄把职责又粘回去
- 接口定义要窄而准,比如 EmailService 只暴露 send(),不暴露 SMTP 配置细节
方法和模块也适用 SRP
一个方法也不该干多件事:
- saveUser() 里既校验、又保存、又发短信 → 违反 SRP
- 拆成 validate()、repository.save()、notification.send() → 各自独立演进
- 模块级同样适用:用户中心、订单中心、通知中心应物理隔离,不共享内部实现
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










