Не следует слишком строго следовать правилам, которые вытекают из закона Деметры.Необходимо понять смысл и цель этого закона.Соблюдение закона Деметры помогает нам избежать лишних зависимостей кода от внешних классов и компонентов.Один из принципов этого закона говорит нам следующее:
Каждая единица должна иметь только ограниченные знания о других единицах: только единицы, «тесно связанные» с текущей единицей
В вашем примере 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 и зависит от него.У нас одинаковые зависимости во всех трех случаях.