迪米特法则

  父母都会教育孩子们,不要和陌生人讲话,如果有陌生人试图和他们讲话,必须告诉爸爸妈妈,这是因为孩子们还不成熟,会相信一切成人告诉他们的事情,我们这样做是为了包含他们。

  在面向对象编程中,我们有类似对象原则,我们要让我们的对象不要和陌生人交谈,什么是和陌生人交谈 ?下面以PHP代码为例,比如:

<?php

 $this->someObject

     ->someOtherObject

     ->someMethod()

     ->someReturnedObject

     ->someOtherMethod()

     ->someFinalMethod();

  这里我们的对象涉及到六个对象交互,这是很多对象了,这些对象可能是某个API的,其中可能会改变,一旦改变就会破坏我们的代码,影响我们的功能。

 

迪米特The Law of Demeter

  面向对象有一个概念是迪米特法则,其规则如下:

  • 每个对象对其他对象的认识必须限制,只能与自己最近的对象
  • 每个对象应当只和它的朋友联系,而不是陌生人
  • 每个对象应当只和他的直接朋友联系。

  这些在设计时意味什么呢?

  首先,一个对象只能知道它能和它一起完成工作的对象,至于其他无关的对象不要传给这个对象,这样就不会产生不必要的耦合,假如将很多其他对象一起传给一个对象,这就犯错误了,一个对象应该值被告诉与其工作有关的对象即可。

  方法链条式的调用有可能是破坏这个法则,开始演示的案例破坏了迪米特法则,因为它是一个链条式的串联调用,这是一种“reaching through”式的访问对象,如果这条链条中某个API改变了,也就破坏了我们的代码。为了处理如此复杂的操作,有一些策略可以改进,比如为这个操作创建某个Adapter类或包装器,也许这里需要一个服务,总之需要重构,降低调用路径的数量。

  但是fluent接口并不违背迪米特法则,比如:

$object->someMethod()

       ->someOtherMethod()

       ->someFinalMethod();

  这个看上去违反了迪米特,但是有区别:这里所有操作都发生在一个对象上,即使这些操作是调用其他对象,但是调用者并不关心操作的具体行为,整个是封装的。

  另外,方法返回其他对象也不违反,一些方法返回其他对象作为响应,这并不违反迪米特法则,这是因为当你将一个对象作为响应调用时,你们之间有了一个合约,因此你们是朋友。这可能有点棘手,

 

迪米特发展与领域模型行为