首页/开发/代码质量与评审速查/迪米特法则(Law of Demeter)
设计原则与模式62 条

迪米特法则(Law of Demeter)

对象只与「直接朋友」通信:优先调用自身、参数、自建对象的方法,避免 a.getB().getC().do();降低对对象图结构的耦合,但不必教条化。

迪米特法则是什么

迪米特法则又叫最少知识原则:对象只与直接朋友通信——优先调用自身、字段、参数与刚创建对象上的方法,避免连续穿越对象图取数据。它能降低对内部结构的耦合,但不必教条化:流式接口与数据组装场景里,链式调用是刻意设计。

基本信息

别名最少知识原则
允许的调用自身、字段、参数、返回值上的方法
限制对返回对象再取对象继续调用
例外流式 API、数据组装与转换层
判断依据对象图的结构是否成为外部依赖

典型使用场景

  • 取值表达式穿过好几层对象才拿到目标字段
  • 业务函数里拼接另一个对象的内部字段
  • 报表组装时大量取深层字段
  • 服务层直接操作实体内部的集合结构
  • 跨模块取数,却被对方内部结构调整牵连

正反例

正反例
// 违反:链式穿越,外部依赖了对象图的层次结构
String zipOf(Person p) { return p.getAddress().getZip(); }

// 改善:让对象自己回答
class Person {
    String zipCode() { return address.zip(); }
}

允许与限制

情形说明建议
调用自身与字段的方法直接朋友允许
调用作为参数传入对象的方法直接朋友允许
对返回值再取对象调用穿越对象图尽量避免
链式构造与集合流式操作刻意的接口设计可以接受
判断依据是对象图结构是否成为外部依赖:如果对方调整内部层次就让调用方大面积编译失败,说明已经穿越过头了。
为绕过法则加一堆转发方法,会造出中间人坏味道:方法只是转手调用,类体积膨胀,真正做事的对象反而更难找。
在数据转换层可以放宽:视图组装、报表导出这类只读场景,适度穿透对象图比逐层加转发方法更清晰,重点是别把内部结构当成长期契约。

易错点

  • 机械禁止一切链式调用:流式构造与集合操作无处安放,代码反而更啰嗦
  • 为绕过法则加一堆转发方法:中间人坏味道出现,类体积膨胀
  • 把法则当硬规范:性能敏感路径上层层转发,调用链变长
  • 只看写法不看依赖方向:真正的耦合来自对内部数据结构的假设,而不是点号数量

数据来源与参考

  • Northeastern University 迪米特法则研究(Karl Lieberherr 等);《Clean Code》引用
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌