цитируя отсюда: https://en.wikipedia.org/wiki/Law_of_Demeter
Более формально, закон Деметры для функций требует, чтобы метод
m объекта O может вызывать только методы следующих
Объекты: [2]
О себе
параметры м
Любые объекты, созданные / созданные в течение м
Прямые составляющие объекты О
Глобальная переменная, доступная O, в
размах мВ частности, объект должен избегать вызова методов члена
объект, возвращенный другим методом
так в деталях:
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
но заводской. Но эй! Закон гласил:
В частности, объект должен избегать вызова методов объекта-члена, возвращаемого другим методом
по этому правилу метод фабрики не работает! Что теперь? Это действительно терпит неудачу?
Я так не думаю.
Особенно это:
Любые объекты, созданные / созданные в м
Я бы применил это и к фабрике. Даже если строго конструктор объекта вызывается на фабрике, объект все еще создается, и особенно за м. Я бы интерпретировал фабрику как конструктор особого типа и посмотрел бы мимо того факта, что вы не видите new
Ключевое слово там.
Учитывая различные важные роли, которые фабрики играют в разработке программного обеспечения (инверсия управления — одна из них), я думаю, что они слишком ценны, чтобы их отпустить. Лучше изменить вашу интерпретацию этого закона или того, что такое конструктор, и использовать эти фабрики, когда захотите.
Не следует слишком строго следовать правилам, которые вытекают из закона Деметры. Необходимо понять смысл и цель этого закона.
Соблюдение закона Деметры помогает нам избежать лишних зависимостей кода от внешних классов и компонентов. Один из принципов этого закона говорит нам следующее:
В вашем примере O класс знает класс C в любом случае. Использование фабрики не влияет на этот факт. Так или иначе класс O зависит от класса C, и эта зависимость неизбежна. Это означает, что зависимость не является избыточной. На самом деле зависимость между классом C и классом O — это зависимость между «тесно связанными» единицами, поэтому не существует нарушения закона Деметры, если вы используете фабрику.
В качестве примера давайте представим следующий экземпляр кода:
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-классом. Как и в предыдущих случаях, класс O знает класс C и зависит от него.
У нас одинаковые зависимости во всех трех случаях.