- Внедрение зависимостей
Внедрение зависимости (англ. Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «инверсии управления» (англ. Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единственной ответственности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму
Внедрение зависимостей
Внедрение зависимостей — термин, придуманный Мартином Фавлером, и означающий внедрение компонентов в ваше приложение. Как сказал Вард Канингхэм:
Внедрение зависимостей является ключевым элементом гибкой архитектуры.
Давайте посмотрим на пример:
class UserProvider{ protected $connection; public function __construct(){ $this->connection = new Connection; } public function retrieveByCredentials( array $credentials ){ $user = $this->connection ->where( 'email', $credentials['email']) ->where( 'password', $credentials['password']) ->first(); return $user; } }
Чтобы тестировать и поддерживать этот класс, вам надо будет получать доступ к реальной БД и выполнять какие-либо запросы. Чтобы избежать этой необходимости и отделить класс от остальных, у вас есть три варианта внедрения класса Connection
без его прямого использования.
При внедрении компонентов в ваш класс вы можете использовать один из трёх вариантов:
Внедрение конструктора
class UserProvider{ protected $connection; public function __construct( Connection $con ){ $this->connection = $con; } ...
Внедрение сеттера
Аналогичным образом мы можем внедрить нашу зависимость с помощью метода сеттера:
class UserProvider{ protected $connection; public function __construct(){ ... } public function setConnection( Connection $con ){ $this->connection = $con; } ...
Внедрение интерфейса
interface ConnectionInjector{ public function injectConnection( Connection $con ); } class UserProvider implements ConnectionInjector{ protected $connection; public function __construct(){ ... } public function injectConnection( Connection $con ){ $this->connection = $con; } }
Когда класс реализует наш интерфейс, мы определяем метод injectConnection
для разрешения зависимости.
Преимущества
Теперь при тестировании нашего класса мы можем подделать класс зависимости и передать его как параметр. Каждый класс должен быть сосредоточен на конкретной задаче и не должен заботиться о разрешении своих зависимостей. Таким образом у вас будет нацеленное на решение задач, поддерживаемое приложение.
Если вы захотите узнать больше о внедрении зависимостей, Алехандро Гервасио рассмотрел его широко и профессионально в этой серии статей, поэтому не забудьте прочесть их. А что насчёт IoC? IoC (Inversion of control — Инверсия управления) не обязательна для использования внедрения зависимостей, но она может помочь вам эффективно управлять вашими зависимостями.