Доступ к контейнеру DI

Я запускаю новый проект и настраиваю основу, чтобы продолжить работать. Несколько вопросов повысились, и я буду, вероятно, спрашивать довольно многих в здесь, надо надеяться, я найду некоторые ответы.

Первый шаг должен обработать зависимости для объектов. Я решил пойти с шаблоном разработки внедрения зависимости, к которому я являюсь несколько новым, для обработки всего этого для приложения.

На самом деле кодируя его я столкнулся с проблемой. Если класс имеет несколько зависимостей, и Вы хотите передать несколько зависимостей через конструктора (так, чтобы они не могли быть изменены после инстанцирования объекта).

Как дела это, не передавая массив зависимостей, с помощью call_user_func_array (), оценка () или Отражение? Это - то, что я ищу:

<?php

class DI
{
    public function getClass($classname)
    {
        if(!$this->pool[$classname]) {
            # Load dependencies
            $deps = $this->loadDependencies($classname);

            # Here is where the magic should happen
            $instance = new $classname($dep1, $dep2, $dep3);

            # Add to pool
            $this->pool[$classname] = $instance;

            return $instance;
        } else {
                return $this->pool[$classname];
        }
    }
}

Снова, я хотел бы избежать самых дорогостоящих методов для вызова класса. Какие-либо другие предложения?

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

Спасибо все.

10
задан Matthieu Napoli 26 December 2012 в 23:11
поделиться

3 ответа

[Прежде чем я начну, позвольте мне скажем, что я в основном программист на Java - с небольшими знаниями PHP. Но я просто попытаюсь передать наиболее важные концепции без языковой специфики.]

Внедрение зависимостей основано на двух частях кода:

  1. Конструкция
  2. Выполнение

В наиболее экстремальной форме есть в части выполнения нет новых операторов. Все они перенесены в часть «Строительство». (На практике это будет приглушено.)

Вся конструкция происходит - в части «Строительство». Создает график объектов, необходимых для выполнения снизу вверх. Итак, предположим, он должен построить A:

  • A зависит от B, а
  • B зависит от C.

Затем

  • C конструируется первым.
  • Затем B строится с C в качестве параметра.
  • Затем A строится с параметром B.

Таким образом, C не нужно передавать в качестве параметра конструктора в A.Этот небольшой пример недостаточно хорошо иллюстрирует, насколько это уменьшает количество объектов, которые необходимо передать, до довольно небольшого числа.

Сам инжектор зависимостей не следует передавать в часть выполнения. Это одна из основных ошибок, которую каждый (включая меня) пытается сделать, когда впервые встречается с DI. Проблема в том, что это полностью стирает границы между Построением и Исполнением. Другими словами, это нарушило бы Закон Деметры . Или, говоря о шаблоне: в конечном итоге он «ухудшит» шаблон внедрения зависимостей до шаблона Service Locator. Спорный вопрос, действительно ли это ухудшение, но в любом случае обычно не рекомендуется злоупотреблять Инжектором зависимостей в качестве локатора сервисов .

Таким образом, всякий раз, когда вам нужно дать одному из ваших сконструированных объектов возможность создавать другие объекты во время выполнения, вместо передачи инжектора зависимостей вы должны передавать только простые провайдеры (термин, используемый платформой Java DI Guice ). Это довольно простые классы, которые могут создавать только объекты определенного типа. У них есть сходство с фабрикой.

Сначала попробуйте передать необходимые зависимости непосредственно конструктору.

Итак, подведем итог:

  • Строим объекты снизу вверх.
  • Передайте только минимальное количество зависимостей, необходимое для создания объекта.
  • Как только вы закончите, приступайте к выполнению.
  • Во время выполнения вы все еще можете получать вновь созданные объекты с помощью Провайдеров.

Но не заходите слишком далеко: простые объекты все еще можно создавать без Provider: -)

И теперь все, что вам нужно сделать, это перевести все это в качественный код. Может быть, другие помогут вам с помощью нескольких примеров PHP.

Приложение: еще немного о поставщиках

Как отмечалось выше, понятие «поставщик» (специализированная фабрика) немного специфично для среды Java DI Guice. Эта структура может автоматически создавать поставщика для любого типа объекта. Однако эта концепция обычно полезна для DI. Единственное отличие состоит в том, что без помощи Guice или подобного фреймворка вам придется писать провайдеров самостоятельно - но это довольно просто:

Допустим, B зависит от C.

  • Если B просто нужен один фиксированный экземпляр C, тогда вам не нужен поставщик - вы можете просто построить B с аргументом конструктора C.
  • Если B нужно создать больше экземпляров C во время выполнения, просто напишите класс с именем CProvider с методом get () , который может создать новый экземпляр C. Затем передать экземпляр CProvider в конструктор B и сохранить Provider в экземпляре поле B. Теперь B может вызвать cProvider.get () , когда ему нужен новый экземпляр C.

Провайдеры являются частью строительного кода, поэтому вам разрешено использовать new C (...) ! С другой стороны, они не являются частью кода выполнения, поэтому у вас не должно быть там никакой логики выполнения.

CProvider , конечно, можно передать в несколько конструкторов.Вы также можете написать несколько версий CProvider1 , CProvider2 , ... - каждая из которых может создавать разные версии объектов C с разными свойствами. Или вы просто создаете экземпляр CProvider несколько раз с разными аргументами.

23
ответ дан 3 December 2019 в 15:51
поделиться

Похоже, вы пытаетесь свернуть собственный контейнер для внедрения зависимостей. Почему бы не использовать уже существующий, например Symfony , Crafty или Sphicy ?

2
ответ дан 3 December 2019 в 15:51
поделиться

Вам следует изучить возможность использования контейнера IOC для управления своими зависимостями за вас. Хороший контейнер IOC должен позаботиться о передаче зависимостей между зависимыми подрядчиками.

Существует вопрос о параметрах контейнера IOC для PHP.

2
ответ дан 3 December 2019 в 15:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: