迪米特法则是什么
迪米特法则又叫最少知识原则:对象只与直接朋友通信——优先调用自身、字段、参数与刚创建对象上的方法,避免连续穿越对象图取数据。它能降低对内部结构的耦合,但不必教条化:流式接口与数据组装场景里,链式调用是刻意设计。
基本信息
| 别名 | 最少知识原则 |
|---|---|
| 允许的调用 | 自身、字段、参数、返回值上的方法 |
| 限制 | 对返回对象再取对象继续调用 |
| 例外 | 流式 API、数据组装与转换层 |
| 判断依据 | 对象图的结构是否成为外部依赖 |
典型使用场景
- 取值表达式穿过好几层对象才拿到目标字段
- 业务函数里拼接另一个对象的内部字段
- 报表组装时大量取深层字段
- 服务层直接操作实体内部的集合结构
- 跨模块取数,却被对方内部结构调整牵连
正反例
正反例
// 违反:链式穿越,外部依赖了对象图的层次结构
String zipOf(Person p) { return p.getAddress().getZip(); }
// 改善:让对象自己回答
class Person {
String zipCode() { return address.zip(); }
}允许与限制
| 情形 | 说明 | 建议 |
|---|---|---|
| 调用自身与字段的方法 | 直接朋友 | 允许 |
| 调用作为参数传入对象的方法 | 直接朋友 | 允许 |
| 对返回值再取对象调用 | 穿越对象图 | 尽量避免 |
| 链式构造与集合流式操作 | 刻意的接口设计 | 可以接受 |
判断依据是对象图结构是否成为外部依赖:如果对方调整内部层次就让调用方大面积编译失败,说明已经穿越过头了。
为绕过法则加一堆转发方法,会造出中间人坏味道:方法只是转手调用,类体积膨胀,真正做事的对象反而更难找。
在数据转换层可以放宽:视图组装、报表导出这类只读场景,适度穿透对象图比逐层加转发方法更清晰,重点是别把内部结构当成长期契约。