Понимание контейнеров 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 ответ:
проще говоря (потому что это не проблема, ограниченная только миром ООП), a зависимость это ситуация, когда компонент A нуждается (зависит от) компонента B, чтобы делать то, что он должен делать. Это слово также используется для описания зависимого компонента в этом сценарии. Чтобы выразить это в терминах ООП / PHP, рассмотрим следующий пример с обязательной аналогией автомобиля:
class Car { public function start() { $engine = new Engine(); $engine->vroom(); } }
Carзависит onEngine.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объект в зависимости от
Comments