quoting from here: https://en.wikipedia.org/wiki/Law_of_Demeter
More formally, the Law of Demeter for functions requires that a method m of an object O may only invoke the methods of the following kinds of objects:[2]
O itself
m's parameters
Any objects created/instantiated within m
O's direct component objects
A global variable, accessible by O, in the scope of m
In particular, an object should avoid invoking methods of a member object returned by another method
so in details:
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() {}
}
now the 3rd law is questionable. So I newly created an object. But if I instead of:
(new C())->a();
I do:
$this->factory->createC()->a();
is it still valid? A regular class was instantized, just not by new
but a factory. But hey! The Law said:
In particular, an object should avoid invoking methods of a member object returned by another method
by this rule, the factory method fails! Now what? Does it really fail?
I don't think so.
Especially this:
Any objects created/instantiated within m
I would apply that to the factory as well. Even though strictly the object's constructor is called in the factory, the object is still constructed by, and especially for m. I would interpret the factory as a special kind of constructor, and look past the fact that you don't see a new
keyword there.
Given the various important roles that factories play in software design (inversion of control is one of them), I think they are too valuable to let go. It's better to change your interpretation of this law, or of what a constructor is and use those factories when you want.