Понимание контейнеров IoC и инъекции зависимостей


Быстрая Перемотка Вперед:

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

на данный момент я попытался прочитать документацию для различных фреймворков(laravel, fuel, codeigniter, symfony), и я обнаружил, что существует слишком много различных аспектов фреймворки, которые мне нужны, чтобы чувствовать себя комфортно, используя его, что я решил попробовать просто изучить каждую из основных частей индивидуально, прежде чем пытаться использовать их в самих фреймворках.

Я потратил часы на поиск различных значений, просматривая ответы stackoverflow и читая различные статьи, пытаясь понять, что такое IoC и как его использовать для правильного управления зависимостями, и я считаю, что понимаю, что это такое в концепции, но я все еще серый о том, как реализовать это правильно. Я думаю, что лучший способ для тех, кто читает это, чтобы помочь мне, чтобы дать то, что мое текущее понимание контейнеров МОК и инъекции зависимости, а затем пусть люди, которые имеют лучшее понимание, чем я указать, где мое понимание не хватает.

в моем понимании:

  • зависимость-это когда экземпляр ClassA требует экземпляр ClassB для создания нового экземпляра ClassA.
  • A инъекция зависимостей - это когда ClassA передается экземпляр ClassB, либо через параметр в конструкторе ClassA, либо через функцию set~DependencyNameHere~(~DependencyNameHere~ $param). (это одна из областей, в которых я не совсем уверен).
  • контейнер IoC является одноэлементным классом (может иметь только один экземпляр экземпляра в любой момент времени), где может быть зарегистрирован конкретный способ создания экземпляров объектов этого класса для этого проекта. вот ссылка на пример того, что я пытаюсь описать вместе с определением класса для контейнера IoC, который я использую

Итак, на этом этапе я начинаю использовать контейнер IoC для более сложных сценариев. На данный момент кажется, что для использования контейнера IoC я ограничен отношением has-a для почти любого класса, который я хочу создать, который имеет зависимости, которые он хочет определить в контейнере IoC. Что делать, если я хочу создать класс, который наследует класс, но только если родительский класс был создан определенным образом он был зарегистрирован в МОК контейнер.

Итак, например: я хочу создать дочерний класс mysqli, но я хочу зарегистрировать этот класс в контейнере IoC, чтобы только создать экземпляр с родительским классом, построенным таким образом, который я ранее зарегистрировал в контейнере IoC. Я не могу придумать способ сделать это без дублирования кода (и поскольку это учебный проект, я пытаюсь его сохранить как "чистым", как это возможно). вот еще несколько примеров того, что я пытаюсь описать.

Итак, вот некоторые из моих вопросов:

  • то, что я пытаюсь сделать выше, возможно, не нарушая какой-то принцип ООП? Я знаю, что в c++ я мог бы использовать динамическую память и конструктор копирования для ее выполнения, но я не смог найти такую функциональность в php. (Я признаю, что у меня очень мало опыта использования любого из других магические методы помимо _ _ construct, но из чтения и _ _ clone, если я правильно понял, я не мог использовать его в конструкторе, чтобы сделать дочерний класс, создаваемый экземпляром, клоном экземпляра родительского класса).
  • куда должны идти все мои определения классов зависимостей по отношению к МОК? (Должен ли мой МОК.php просто есть куча require_once ('dependencyClassDefinition.РНР') в верхней? Моя внутренняя реакция заключается в том, что есть лучший способ, но я его не придумал пока)
  • в каком файле я должен регистрировать свои объекты? В настоящее время делает все звонки в МОК::регистрация() в МОК.php файл после определения класса.
  • нужно ли регистрировать зависимость в IoC, прежде чем я зарегистрирую класс, который нуждается в этой зависимости? Поскольку я не вызываю анонимную функцию, пока я фактически не создам экземпляр объекта, зарегистрированного в IoC, я предполагаю, что нет, но его все еще беспокоит.
  • есть ли что-нибудь еще, что я пропускаю что я должен делать или использовать? Я пытаюсь сделать это шаг за шагом, но я также не хочу знать, что мой код будет повторно использоваться и, самое главное, что кто-то, кто ничего не знает о моем проекте, может прочитать его и понять.

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

1   51   2013-09-02 00:45:10

1 ответ:

проще говоря (потому что это не проблема, ограниченная только миром ООП), a зависимость это ситуация, когда компонент A нуждается (зависит от) компонента B, чтобы делать то, что он должен делать. Это слово также используется для описания зависимого компонента в этом сценарии. Чтобы выразить это в терминах ООП / PHP, рассмотрим следующий пример с обязательной аналогией автомобиля:

class Car {

    public function start() {
        $engine = new Engine();
        $engine->vroom();
    }

}

Carзависит on Engine. Engine и Car ' s зависимость. Этот кусок кода довольно плохо, хотя, потому что:

  • зависимость неявная; вы не знаете, что она есть, пока не проверите Car ' s code
  • классы тесно связаны; вы не можете заменить Engine С MockEngine для целей тестирования или TurboEngine что расширяет исходный без изменения Car.
  • это выглядит как-то глупо для автомобиля, чтобы иметь возможность построить двигатель для себя, не это?

инъекции зависимостей это способ решения всех этих проблем, сделав тот факт, что Car должен Engine явное и явное предоставление ему одного:

class Car {

    protected $engine;

    public function __construct(Engine $engine) {
        $this->engine = $engine;
    }

    public function start() {
        $this->engine->vroom();
    }

}

$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);

выше приведен пример конструктор инъекций, в котором зависимость (зависящий от объекта) предоставляется зависимому (потребителю) через конструктор класса. Другим способом было бы разоблачение setEngine метод Car класс и используя его, чтобы ввести экземпляр Engine. Это известно как сеттер инъекций и используется в основном для зависимостей, которые должны быть заменены во время выполнения.

любой нетривиальный проект состоит из множества взаимозависимых компонентов, и его легко потерять из виду, что вводится, где довольно быстро. А контейнер для инъекций зависимостей это объект, который знает, как создавать и настраивать другие объекты, знает, что их отношения с другими объектами в проекте есть и делает инъекцию зависимостей для вас. Это позволяет централизовать управление всеми зависимостями вашего проекта (inter)и, что более важно, позволяет изменять/имитировать один или несколько из них без необходимости редактировать кучу мест в вашем коде.

давайте отбросим аналогию с автомобилем и посмотрим, что OP пытается достичь в качестве примера. Допустим, у нас есть Database объект в зависимости от