迪米特法则要求只与直接朋友交互:当前对象、参数对象、成员变量、方法内新建对象及集合元素(仅一层);禁止链式调用如order.getcustomer().getaddress().getcity(),应封装为高阶方法并隐藏实现细节。

迪米特法则(Law of Demeter),也叫最少知识原则,核心就一句话:只和直接朋友说话,不跟陌生人打交道。它不是讲“少写代码”,而是讲“少依赖、少暴露、少穿透”。应用得当,类之间关系清爽,改一个地方不容易牵一发动全身。
明确谁是“直接朋友”
判断一个对象能不能调用另一个对象的方法,先看它是不是你的“朋友”。朋友只包括这几类:
- 当前对象自己(
this) - 方法参数传进来的对象
- 当前对象的成员变量(字段)
- 方法内部新创建的对象
- 如果成员是集合,集合里的元素也算朋友(但仅限这一层)
比如 order.getCustomer().getAddress().getCity() 这种链式调用,order 和 customer 是朋友,customer 和 address 是朋友,但 order 和 address 不是朋友——这就违规了。
避免“火车车厢式”调用
常见反模式:library.getShelf().getBooks().get(0).getAuthor().getName()。这等于让 library 知道了 shelf、books、Book、Author 四层结构,任意一层改了,都可能让调用方崩溃。
正确做法是把逻辑封装到更靠近数据源的地方:
- 在
Library类里加个方法:getFirstBookAuthorName() - 或在
Shelf里提供getFirstBookAuthor(),Library只调一层 - 外部只需调
library.getFirstBookAuthorName(),完全不关心内部怎么组织
用接口或委托隐藏实现细节
当需要跨多层获取信息时,优先通过中间对象转发,而不是层层扒开:
- 老板要查课程数,不该自己构造
List<course></course>再传给 Leader;而应让 Leader 自己统计,老板只调leader.checkCourseCount() - 订单处理中,
Order不该直接调customer.getAddress().getZipCode(),而应在Customer中提供getShippingZipCode()方法 - 这样即使地址结构重构(比如拆成
PostalAddress和ResidentialAddress),Order完全无感
控制访问权限,减少不必要的暴露
很多违反迪米特法则的代码,根源在于过度公开:
- 把本该 private 的方法设为 public,让外部能绕过业务逻辑直接操作底层
- 返回可变集合(如
public List<product> getProducts()</product>),调用方可能误删或修改,破坏封装 - 改法:返回
Collections.unmodifiableList(products),或提供只读视图方法 - 内部字段尽量 private,getter/setter 按需提供,不为“方便”而开放










