【问题标题】:A factory method may violate the Law Of Demeter?工厂方法可能违反得墨忒耳定律?
【发布时间】:2019-04-30 22:40:32
【问题描述】:

从这里引用:https://en.wikipedia.org/wiki/Law_of_Demeter

更正式地说,函数的得墨忒耳定律要求一个方法 对象 O 的 m 只能调用以下类型的方法 对象:[2]

  • O 本身

  • m的参数

  • 在 m 中创建/实例化的任何对象

  • O 的直接组件对象

  • 一个全局变量,可由 O 访问,在 m的范围

特别是,对象应避免调用成员的方法 另一个方法返回的对象

详情如下:

class O
{
    private $c;
    public function m($obj1)
    {
        $this->a(); // OK
        $obj1->a(); // OK
        (new C())->a(); // OK
        $c->a(); // OK
        $a = function() { };
        $a(); // OK
    }

    private function a() {}
}

现在第三定律是有问题的。所以我新创建了一个对象。但如果我不是:

(new C())->a();

我愿意:

$this->factory->createC()->a();

它仍然有效吗?一个普通的类被实例化了,只是不是由new 而是一个工厂。但是,嘿!法律说:

特别是,一个对象应该避免调用另一个方法返回的成员对象的方法

按照这个规则,工厂方法失败了!怎么办?真的失败了吗?

【问题讨论】:

    标签: php oop factory law-of-demeter


    【解决方案1】:

    我不这么认为。

    尤其是这个:

    m

    中创建/实例化的任何对象

    我也会将其应用于工厂。尽管严格来说对象的构造函数是在工厂中调用的,但对象仍然是由 for m 构造的。我会将工厂解释为一种特殊的构造函数,并忽略您在那里看不到 new 关键字的事实。

    考虑到工厂在软件设计中扮演的各种重要角色(控制反转就是其中之一),我认为它们太有价值了,不能放手。最好改变你对这条定律或构造函数的解释,并在需要时使用这些工厂。

    【讨论】:

      【解决方案2】:

      不应该太严格地遵循源自得墨忒耳法则的规则。有必要了解这项法律的意义和目的。 遵守得墨忒耳定律有助于我们避免代码对外部类和组件的过度依赖。该法的其中一项原则告诉我们:

      Each unit should have only limited knowledge about other units: only units "closely" related to the current unit

      在您的示例中,O 类无论如何都知道 C 类。使用工厂不会影响这一事实。不知何故,另一个 O 类依赖于 C 类,这种依赖是不可避免的。这意味着依赖并不过分。实际上C类和O类之间的依赖是“密切”相关单元之间的依赖,因此如果使用工厂,则不违反Demeter定律。

      作为一个例子,让我们想象下面的代码实例:

      class O
      {
      
         public function m()
         {
            $c = new C();
            $c->a();
         }
      }
      

      如您所见,O 类知道 C 类并依赖于它。本守则没有违反得墨忒耳法则。如果您将这个示例修改为:

      class O
      {
      
         protected function build()
         {
            return new C();
         }
      
         public function m()
         {
            $c = $this->build();
            $c->a();
         }
      }
      

      O 类仍然会知道 C 类并依赖它,在这段代码中不会违反得墨忒耳法则。实际上,我们将对象制作的责任委托给了工厂方法。如果您将这个示例修改为:

      class Factory
      {
         public function build()
         {
            return new C();
         }
      }
      
      class O
      {
      
         /**
          * @var Factory
          */
         protected $factory;
      
         public function m()
         {
            $c = $this->factory->build();
            $c->a();
         }
      }
      

      我们将创建对象的责任委托给工厂对象,但这一事实违反了得墨忒耳定律,因为 O 类和 C 类之间的依赖关系不会发生任何变化。作为 prev 实例,O 类知道 C 类并依赖于它。 我们在所有三个实例中都有相同的依赖关系。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-28
        • 1970-01-01
        相关资源
        最近更新 更多