高内聚指一个模块只响应同一类变化、服务同一角色、表达同一层语义,体现为命名、行为、状态与修改动因的统一;判断标准是类的核心职责能否用主谓宾业务语句唯一定义,且所有方法共享状态与变化原因。

高内聚不是把代码写得“紧凑”或“放一起”,而是让一个模块只响应同一类变化、只服务同一个角色、只表达同一层语义。它体现在类的命名、方法行为、状态关联和修改动因是否统一。
用一句话定义类的核心职责
拿到一个类,先问:它存在的唯一理由是什么?答案必须是主谓宾结构的业务语句,比如:
- “生成带水印的PDF发票”
- “校验用户手机号格式与运营商归属”
- “执行订单从待支付到已支付的状态跃迁”
如果描述中出现“和”“或”“以及”“辅助”“管理”,或者需要加限定词才能说清(如“既做A又做B,但B只在导出时才用”),那它已经偏离单一职责。
检查方法是否共享同一组状态与变化原因
一个高内聚的类里,所有方法应操作相近的状态字段,并因同一类业务变动而修改。例如:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 高内聚:Order 类包含 status、paidAt、items,方法有 transitionTo(PAID)、cancel()、getTotalAmount()——都围绕订单生命周期与金额计算
- 低内聚:OrderService 同时有 sendEmail()(邮件策略变就改)、exportToExcel()(模板格式变就改)、calculateTax()(税率政策变就改)——三个方法响应三种完全无关的变化
IDE 中右键 “Find Usages”,若发现不同模块(如定时任务、Web Controller、消息监听器)各自调用该类的不同方法,说明它实际承担多个角色,该拆了。
把行为封装进数据实体,避免 DTO + 工具类割裂语义
数据和行为分离会稀释内聚。UserDto + UserHelper.isValidEmail(user.getEmail()) 看似解耦,实则让验证逻辑游离于用户本身的状态约束之外。
- 推荐:User.isValidEmail() —— 验证逻辑属于 User 的固有约束,可随 email 字段变更自动生效
- 不推荐:UserHelper.isValidEmail(String) —— 调用方需记住何时校验、如何传参,逻辑无法复用也无法追踪
DTO 只用于跨层传输(如 Controller → Service),不参与任何判断、格式化或校验;真实业务行为应落在 Entity、Domain Object 或专用领域类中。
拒绝“上帝类”,按变化维度垂直拆分
当一个类开始处理多种技术场景或业务分支(如 if (type.equals("alipay")) 或 switch (format)),它就在承担多个变化原因。此时应按“谁会变、为什么变”来切分:
- 支付方式切换 → 提取 PaymentStrategy 接口,由 AlipayPayment、WechatPayment 实现
- 日志输出渠道变更 → 提取 AuditLogger 接口,由 DbAuditLogger、KafkaAuditLogger 实现
- 用户认证流程升级 → 提取 Authenticator 接口,由 JwtAuthenticator、OidcAuthenticator 实现
每个实现类只守自己那一块责任边界,修改不影响其他部分,这才是高内聚的自然结果。

















