封装是高内聚类设计的起点,需通过访问控制、职责收拢和边界明确让类管好自己的事;成员变量默认private,谨慎使用getter/setter,集合防御性返回,构造器校验必填字段,行为归属匹配业务语义,包结构按领域垂直划分,静态方法仅限无状态操作。

封装是高内聚类设计的起点——它不是简单地把字段设为 private,而是通过访问控制、职责收拢和边界明确,让一个类真正“管好自己的事”。高内聚的类,对外接口简洁清晰,对内逻辑紧密协作,不越界、不甩锅、不裸奔。
用最小可见性守住数据边界
成员变量默认用 private,这是底线。不要因为“反正就我一个人写”就放开为 default 或 protected。哪怕只是临时调试,也别动字段可见性——它会悄悄松动类的内聚性。
- getter/setter 不是必须全写:只暴露需要被外部读或改的字段;比如订单状态可读不可写,就只提供
getStatus(),不写setStatus() - 集合类字段要防御性返回:避免
public List<item> getItems()</item>,改用return Collections.unmodifiableList(items)或返回副本 - 构造器参数优先校验:在构造方法里用
Objects.requireNonNull()检查必填字段,拒绝半成品对象
行为归属要匹配业务语义
一个方法该放在哪个类里,关键看“这件事本质上是谁的责任”。不是谁调用它,而是谁拥有相关状态、谁对该规则的正确性负责。
- 金额不能为负?由
Order类自己在setAmount()里校验,而不是等OrderService来判断 - 用户邮箱格式是否合法?
User的setEmail()应完成基础格式检查(非空、含@),但唯一性校验交给UserValidator - 订单能否发货?
order.canShip()是自然表达,比ShippingService.isEligible(order)更内聚——状态和规则绑定在同一个主体上
包结构体现领域聚合力
单个类再干净,如果散落在 util、common、model 等大杂烩包里,整体仍属低内聚。包是第一层职责声明。
- 按业务域垂直切分:如
com.example.ecommerce.order下只放与订单强相关的类(Order、OrderItem、OrderStatus枚举) - 同包内可适度放宽访问:包私有(
default)方法或辅助类,只供本域内协作,不对外暴露 - 避免跨域引用:
user包里的类不应直接 newproduct.ProductPriceCalculator,需通过接口或服务契约交互
静态方法只做无状态的事
静态方法可以高内聚,但前提是它真的不依赖任何实例状态,也不改变任何外部环境。
- 适合的场景:字符串处理(
StringUtils.truncate())、时间换算(TimeUtils.toLocalDateTime(Instant))、安全计算(HashUtils.md5Hex()) - 不适合的场景:操作数据库、发消息、调用远程服务、修改传入对象的字段——这些行为应归属到有生命周期的 Service 或 Domain 类中
- 工具类本身也要高内聚:命名如
EmailTemplateUtils,只管模板渲染;别叫CommonUtils,然后塞进100个无关方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











