封装通过控制可见性、明确职责边界和隐藏实现细节使依赖可控稳定;真正降低耦合需分离“怎么用”与“怎么实现”,依赖接口而非具体类,结合private封装、接口抽象与依赖注入,并遵循单一职责原则。

封装本身不直接“切断”类之间的依赖,但它通过控制可见性、明确职责边界和隐藏实现细节,让依赖变得可控、稳定、不易断裂。真正降低耦合度的关键,是把“怎么用”和“怎么实现”分开——外部只依赖接口或契约,不依赖具体类的内部结构。
用 private + public 接口隔离内部变化
把属性和敏感方法设为 private,只暴露必要且稳定的 public 方法(如 getter/setter 或业务方法)。这样即使内部字段重命名、类型调整、逻辑重构,只要接口签名不变,调用方完全不受影响。
- 例如:User 类里 age 字段改为 long 类型,或增加年龄合法性校验,只需改 setAge() 内部实现,所有调用 user.setAge(25) 的代码都不用动
- 避免直接暴露可变集合:不要写
public List<order> getOrders()</order>,而应返回Collections.unmodifiableList(orders)或提供addOrder()、getOrderCount()等语义化方法
把复杂访问路径封装成有业务含义的方法
禁止链式调用(如 user.getProfile().getAddress().getCity()),这类写法等于把多个类的内部结构“焊死”在调用点上,一改全崩。
- 应在 User 类中提供
getUserCity()或getDeliveryLocation()这样的方法,把路径细节封装起来 - 如果逻辑跨域较重(比如涉及用户、地址、地区服务),可引入协调类(如 LocationService)统一提供
resolveDeliveryCity(userId),进一步收口依赖
结合接口与依赖抽象,让封装真正生效
仅靠 private 不足以降低类间耦合;必须配合面向接口编程。比如 Service 类不应依赖 AccountDaoImpl,而应依赖 IAccountDao 接口。
- 构造器或 setter 中注入接口,而非 new 具体实现类
- 这样 AccountDaoImpl 可随时替换成 MockDao、JpaAccountDao 等,不影响 Service 逻辑
- 封装 + 接口 + 依赖注入三者结合,才能让“低耦合”从理念落地为可维护的代码
聚焦单一职责,让类自己管好自己的事
高内聚是低耦合的前提。一个类如果同时处理用户信息、订单校验、日志记录、HTTP 调用,它必然要和很多其他类强关联。
- User 类只管用户数据和基本行为(如 isActive()、changeEmail())
- 校验逻辑抽成独立的 Validator 类,通过参数传入需要检查的对象
- 日志、通知等横切关注点,用 AOP 或事件机制解耦,不塞进业务类里
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











