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

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

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

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

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


person LordMagik    schedule 07.03.2015    source источник
comment
Обновите свой вопрос, приведя пример того, как второй вариант может быть решен с помощью статических свойств. Рассмотрите возможность использования примера PHP-DI StoreService из php-di.org/doc/understanding-di .html   -  person Cerad    schedule 07.03.2015


Ответы (1)


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

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

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

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

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

Теперь Контейнер внедрения зависимостей - это просто хороший помощник для более простого управления экземплярами объектов и их зависимостями, но он не нужен для внедрения зависимостей.

person hanzi    schedule 07.03.2015