封装通过控制可见性、明确职责边界和隐藏实现细节使依赖可控稳定;关键在于分离“怎么用”与“怎么实现”,依赖契约而非具体实现,结合接口抽象、协调层收口、职责单一化等手段降低耦合。

封装本身不直接“切断”模块间的依赖,但它通过控制可见性、明确职责边界和隐藏实现细节,让依赖变得可控、稳定、不易断裂。真正降低耦合的关键,是把“怎么用”和“怎么实现”分开——外部只依赖契约(如接口或稳定方法),不依赖具体模块的内部结构。
用 private + public 接口隔离变化
把模块内部的数据字段、工具方法、构造逻辑设为 private,只暴露少量语义清晰、职责明确的 public 方法(比如 createOrder()、validateEmail())。这样即使内部重构——字段重命名、算法替换、校验规则增强——只要方法签名不变,调用方完全不受影响。
- 避免返回可变集合:不用
public List,改用- getItems()
public int getItemCount()或public Item getItemAt(int index) - 禁止链式调用:不写
user.getProfile().getAddress().getCity(),而是封装成user.getHomeCity()
用接口抽象代替具体模块依赖
一个模块不应直接 new 另一个模块的实现类,也不应 import 具体实现类的包。而应依赖一个独立定义的接口(如 PaymentService),由上层统一注入实现(如 AlipayService 或 WechatPayService)。
- 接口定义放在公共模块或 API 包中,与实现解耦
- 实现类在各自模块内完成,不向调用方暴露
- 通过构造函数或 setter 注入接口实例,便于测试时替换为 mock 实现
把跨模块逻辑收口到协调层
当多个模块频繁互相调用(如用户模块要查订单、订单模块又要回查用户状态),容易形成隐性环形依赖。此时应抽离出一个协调者模块(如 OrderWorkflow 或 UserOrderFacade),统一处理跨域逻辑,其他模块只与它通信。
- 协调层负责组合调用,不包含核心业务规则
- 原模块退回到单一职责:用户模块只管用户数据,订单模块只管订单状态
- 必要时引入事件机制:用户更新后发
UserUpdatedEvent,订单模块监听并响应,彻底解除直接引用
聚焦职责单一,减少被动依赖
一个模块如果同时做校验、日志、缓存、通知、HTTP 调用,它必然要和很多其他模块强绑定。高内聚是低耦合的前提。
- 校验逻辑单独抽成
EmailValidator,通过参数传入待校验对象 - 日志、埋点等横切关注点,用 AOP 或事件发布,不硬编码在业务方法里
- 配置项外置(如 YAML/JSON),模块只读取键名,不关心来源










