迪米特法则要求类只与直接朋友交互,禁止链式调用,改用语义化委托;通过门面类统一收口跨域协作;返回集合时避免泄露内部可变引用。

迪米特法则(Law of Demeter)在 Java 中减少类之间直接耦合,核心不是切断通信,而是把通信“收口”“限深”“藏细节”。它不追求零依赖,而是让依赖变得可控、可预测、不易断裂。
明确谁是“直接朋友”
一个类只允许与以下几类对象直接交互:
- 自身创建的对象(如
new ArrayList()) - 方法参数传入的对象
- 作为成员变量持有的对象(即字段引用)
- 全局可访问的常量或静态工具类(需谨慎)
而局部变量中临时创建或获取的对象,不属于直接朋友。比如 user.getAddress().getCity().getName() 中,getAddress() 返回的是朋友,但 getCity() 和 getName() 就越级了——这正是耦合失控的典型信号。
禁用链式调用,改用语义化委托
把深层访问封装成有业务含义的方法,既符合直觉,又隔离变化:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- ❌ 违反:
order.getCustomer().getProfile().getPreferences().getLanguage() - ✅ 合规:
order.getCustomerPreferredLanguage()或order.getCustomerLocale()
这个方法可以实现在 Order 类内部,也可以由专门的协调类提供。关键是它隐藏了路径细节,一旦用户档案结构调整(比如偏好移到新服务),只需改一处实现,所有调用点完全不受影响。
用门面类统一收口跨域协作
当多个类需协同完成一个业务动作(如“创建带风控校验的订单”),不要让调用方拼接 userService、productService、riskClient,而是引入一个轻量门面:
- 门面只暴露 高频、稳定、面向场景 的接口,例如
OrderFacade.createOrderWithDefaults(userId, skuId) - 它不持有状态,不写分支逻辑(如 VIP 判断),只做协调和参数预处理
- 调用方从此只依赖
OrderFacade,完全不知道背后涉及几个微服务或数据库表
这种设计天然降低跨模块耦合,也便于统一加监控、熔断、日志或灰度开关。
控制返回值,避免泄露内部可变引用
返回集合或复杂对象时,若直接返回私有字段引用,外部就可能绕过封装修改内部状态:
- ❌ 危险:
public List<item> getItems() { return items; }</item>—— 外部可 add/remove - ✅ 安全:
public List<item> getItems() { return Collections.unmodifiableList(items); }</item>或返回副本
这属于迪米特法则的延伸实践:不仅限制“跟谁说话”,也限制“说了什么话”——不暴露可被滥用的内部结构。

















