PHP-DI - различия между фабриками и объектами
PHP-DI позволяет некоторым методам определять инъекции, включая фабрики и объекты: http://php-di.org/doc/php-definitions.html.
Фабрики:
TestClass::class => function () {
return new TestClass('param');
}
TestClass
экземпляр создается лениво, только когда это нужно.
Объекты:
TestClass::class => DI\object()->constructor('param')
Если вы используете Objects, экземпляр также создается лениво?
Если да, в чем разница между фабриками и объектами?
2 ответа
Автор PHP-DI здесь, кажется, есть некоторая путаница (учитывая вопрос и насколько неправильным является другой ответ). Я улучшил документацию, надеюсь, это прояснит ситуацию: ec8120ee.
Чтобы ответить на ваши вопросы:
Если вы используете Objects, экземпляр также создается лениво?
Да, все определения решаются лениво, object()
тоже.
Если да, в чем разница между фабриками и объектами?
Просто синтаксис. В некоторых случаях более практично написать закрытие, в некоторых других случаях вы можете избежать использования шаблона, используя object()
,
Честно говоря, это просто предпочтение синтаксиса.
РЕДАКТИРОВАТЬ: игнорировать мой пост, см. Сообщение Матье Наполи!
Хороший вопрос, очень важно понимать назначение языковых конструкций в PHP-DI, чтобы эффективно использовать библиотеку.
PHP-DI позволяет создавать объекты с помощью заводских методов, методов объектов, а также позволяет выполнять отложенную загрузку (при условии, что вы установили сопутствующую библиотеку Ocramius Proxy Manager).
ОБЪЕКТЫ
В PHP-DI вы чаще всего используете DI\object()
функция для добавления определений в контейнер. Только после того, как контейнер создан, создается определение. Другими словами, нет ленивой загрузки, вы просто загружаете все сразу. Смотрите этот пример:
$builder = new DI\ContainerBuilder();
$builder->addDefinitions([
TestClass::class => DI\object()->constructor('param')
]);
$container = $builder->build();
$container
объект будет содержать полностью плотный TestClass
объект.
Если вы хотите, чтобы этот объект загружался лениво (причины могут отличаться, см. Сводку ниже), вы можете включить Ocramius Proxy Manager, который необходим для вызова ->lazy()
Цепная функция:
$builder = new DI\ContainerBuilder();
$builder->addDefinitions([
TestClass::class => DI\object()->constructor('param')->lazy()
]);
$container = $builder->build();
В этом случае (см. Выше) ваш объект будет загружен псевдо-ленивым, то есть он не будет существовать должным образом до первого вызова. Вместо этого Ocramius Proxy Manager создает прокси-заглушку объекта, и при первом вызове из контейнера он создается как правильный экземпляр класса.
ФАБРИКИ
PHP-DI также поддерживает фабричные методы для создания базовых объектов. Это удобно, когда у вас есть определенный класс, который вы хотите, чтобы новый экземпляр каждый раз вызывался в вашем коде. Обратите внимание, что это полностью отличается от DI\object()
метод в том, что они являются новыми экземплярами класса - мы используем DI\object()
когда мы хотим использовать один и тот же экземпляр каждый раз, и DI\factory()
когда мы хотим новые экземпляры каждый раз.
PHP-DI имеет существующий язык для фабрик, о котором вы можете не знать:
TestClass::class => DI\factory(function() {
return new TestClass('param');
})->scope(DI\Scope::PROTOTYPE);
Вы заметите, что я был прикован к методу ->scope()
, Этот метод позволяет вам объявить, ограничен ли экземпляр областью действия PROTOTYPE
(каждый раз новое) или SINGLETON
(то же самое каждый раз). Лично я не вижу смысла в SINGLETON
типа, но я предполагаю, что он есть, чтобы удовлетворить желание иметь два способа создания классов с одним экземпляром.
РЕЗЮМЕ
- Вы используете фабричный метод, когда хотите каждый раз создавать новые экземпляры объекта.
- Вы используете метод объекта, когда хотите каждый раз один и тот же экземпляр объекта
- Вы используете ленивый метод, когда хотите отложить создание объекта до тех пор, пока он действительно не понадобится. Это может быть полезно, когда а) у вас есть циклические зависимости, б) создание экземпляра объекта является дорогостоящим, а объект не всегда используется, в) создание экземпляра объекта требует больших затрат памяти и на него следует ссылаться только при наличии достаточного объема памяти. (Вероятно, есть и другие причины, это всего лишь короткий список)