symfony — Зачем использовать компоненты внедрения зависимостей в PHP-фреймворках

Когда я впервые увидел компоненты внедрения зависимостей, такие как PHP-DI, Symfony2 DI и т. Д., Я обнаружил, что существует способ автоматически внедрить экземпляр любого класса в любой с помощью только одного экземпляра.

Так
1. Создайте экземпляр в корневом классе, как $foo = new Foo()
2. И тогда я могу использовать этот экземпляр в любом объекте (например, глобальном синглтоне), не передавая ссылку на конструктор или метод класса, из которого я хочу вызвать.

Но я обнаружил, что в основном я могу использовать Dependency Injection двумя способами
1. Передача ссылки экземпляра в конструктор
2. Создание контейнера, в котором расположены все объекты. Этот контейнер может быть внедрен в другие классы, но «Это не рекомендуется».

Поскольку оба способа могут быть легко реализованы в чистом PHP, первый понятен, второй может быть решен с помощью статических свойств, так зачем использовать PHP-DI или Symfony2 для этой работы?

2

Решение

Почему вы должны использовать Dependency Injection поверх шаблона Singleton?

Давайте предположим, что у нас есть объект Singleton с именем DatabaseConnection который оборачивает соединение с базой данных MySQL для нас и делает некоторые другие интересные вещи, кто знает. Поскольку повторное использование кода — хорошая вещь, мы используем этот объект во многих проектах.

Что если в какой-то момент мы решим переключить один из наших проектов с MySQL на другой продукт баз данных? Мы должны были бы изменить каждое место, где мы называем DatabaseConnection возразить и заменить его нашей новой реализацией. Или мы могли бы изменить сам класс — но мы все еще хотим использовать исходный с другими проектами, поэтому мы в конечном итоге две реализации с одинаковым именем который просто напрашивается на неприятности, правда.

А как насчет юнит-тестов? Мы делаем это, конечно, потому что мы хорошие разработчики! Но если мы проводим модульное тестирование функции, которая использует базу данных, мы не хотим, чтобы тест фактически полагался на базу данных или даже что-то там изменял. Там нет никакого способа заменить DatabaseConnection с фиктивным объектом (который просто возвращает статические данные), потому что наш проект тесно связан с ним.

Вот что делает Dependency Injection: оно помогает предотвратить жесткую связь. Если мы вводим связь с $someObject->setDatabaseConnection($databaseConnection)мы можем внедрить любой объект, который ведет себя как оригинальный. Мы можем внедрить фиктивные объекты, альтернативные реализации или расширения, которые наследуют исходный класс.

Сейчас Контейнер для инъекций зависимостей это просто хороший помощник для более простого управления экземплярами объектов и их зависимостями, но он не нужен для выполнения Dependency Injection.

2

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

Других решений пока нет …

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