Ленивая загрузка невозможна с DI?

Внедрение зависимостей делает невозможным отложенную загрузку зависимостей?

из-за того, что вам нужно передать экземпляры в конструктор, вы не можете сделать экземпляры позже

2

Решение

Внедрение зависимостей делает невозможным отложенную загрузку зависимостей?

Нет, это не делает невозможной загрузку. Я бы даже стал утверждать обратное, и я бы даже сказал, что динамические языки (такие как PHP и Ruby) делают это даже проще, чем языки со статической типизацией (такие как Java и C #).

Поскольку ваши компоненты программируются на абстракции, легко внедрить реализацию для того же контракта, который оборачивает реальную реализацию, которая может быть загружена с отложенным доступом. Обертка действует как прокси, и это позволяет потребителю не обращать внимания на тот факт, что любая ленивая загрузка происходит. Это повышает ремонтопригодность.

Мой PHP довольно ржавый, поэтому следующий пример может не быть «компилируемым» (любой PHP-разработчик, пожалуйста, не стесняйтесь обновлять этот пример), но следующее показывает идею.

Здесь мы видим некоторый класс, который реализует некоторую бизнес-логику (ShipOrderHandler) и это зависит от зависимости логгера:

class ShipOrderHandler {
private $logger;

function __construct($logger) {
$this->logger = $logger;
}

function Handle($command) {
$this->logger->Log("shipping order " + $command->OrderId);
}
}

class DatabaseLogger {

function Log($message) {
// log the message
}
}

Вот как мы могли бы построить граф объектов для ShipOrderHandler:

$handler = new ShipOrderHandler(new DatabaseLogger());

Не представляю DatabaseLogger быть на самом деле тяжелым для инициализации. Используя возможности DI и динамических языков, мы можем просто добавить прокси-реализацию для нашего аннотации логгера; давай называть это LazyLogger, Наш новый LazyLogger может выглядеть следующим образом:

class LazyLogger {
private $loggerFactory;
private $logger;
function __construct($loggerFactory) {
$this->loggerFactory = $loggerFactory;
}

function Log($message) {
if (!$this->logger) $logger = $loggerFactory();
$this->logger.Log($message);
}
}

Теперь мы можем применить это LazyLogger нашим Корень композиции делать DatabaseLogger Создано лениво, без каких-либо изменений в наших компонентах приложения:

$handler = new ShipOrderHandler(
new LazyLogger(function() { return new DatabaseLogger() });

Здесь мы завернем создание DatabaseLogger в анонимной функции, которая вводится в LazyLogger, Когда LazyLogger«s Log метод вызывается впервые, фабричный метод вызывается, DatabaseLogger создан и LazyLogger кэширует этот экземпляр и будет использовать его до тех пор, пока он сам не выйдет из области видимости.

Как видите, Dependency Injection ни в коем случае не ограничивает использование отложенной загрузки; напротив: он позволяет ленивую загрузку без необходимости вносить радикальные изменения по всему приложению.

Это сила DI.

3

Другие решения

Вы найдете пример компонента Symfony DI в http://php.budgegeria.de/flzsbalQV2 где ленивая загрузка используется.

Класс Bar имеет зависимость от Foo, который настроен как сервис. Когда создается Foo, запускается эхо. Как видите, экземпляр будет создан, когда произойдет первый доступ к методу зависимости Foo.

Для этого вам понадобится пакет компоновщика ocramius / proxy-manager. Также возможно реализовать это ленивое поведение для других контейнеров DI.

0

По вопросам рекламы [email protected]