依赖注入模式(Dependency Injection)
目的 用松散耦合的方式来更好的实现可测试、可维护和可扩展的代码。
依赖注入模式:依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。要实现控制反转,通常的解决方案是将创建被调用者实例的工作交由 IoC 容器来完成,然后在调用者中注入被调用者(通过构造器 / 方法注入实现),这样我们就实现了调用者与被调用者的解耦,该过程被称为依赖注入。
用法 DatabaseConfiguration 被注入 DatabaseConnection 并获取所需的 $config 。如果没有依赖注入模式, 配置将直接创建 DatabaseConnection 。这对测试和扩展来说很不好。
例子
Doctrine2 ORM 使用依赖注入。 例如,注入到 Connection 对象的配置。 对于测试而言, 可以轻松的创建可扩展的模拟数据并注入到 Connection 对象中。
Symfony 和 Zend Framework 2 已经有了依赖注入的容器。他们通过配置的数组来创建对象,并在需要的地方注入 (在控制器中)。
代码 DatabaseConfiguration.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <?php namespace DesignPatterns \Structural \DependencyInjection ;class DatabaseConfiguration { private $host ; private $port ; private $username ; private $password ; public function __construct (string $host , int $port , string $username , string $password ) { $this ->host = $host ; $this ->port = $port ; $this ->username = $username ; $this ->password = $password ; } public function getHost ( ): string { return $this ->host; } public function getPort ( ): int { return $this ->port; } public function getUsername ( ): string { return $this ->username; } public function getPassword ( ): string { return $this ->password; } }
DatabaseConnection.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?php namespace DesignPatterns \Structural \DependencyInjection ;class DatabaseConnection { private $configuration ; public function __construct (DatabaseConfiguration $config ) { $this ->configuration = $config ; } public function getDsn ( ): string { return sprintf ( '%s:%s@%s:%d' , $this ->configuration->getUsername (), $this ->configuration->getPassword (), $this ->configuration->getHost (), $this ->configuration->getPort () ); } }
测试 Tests/DependencyInjectionTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php namespace DesignPatterns \Structural \DependencyInjection \Tests ;use DesignPatterns \Structural \DependencyInjection \DatabaseConfiguration ;use DesignPatterns \Structural \DependencyInjection \DatabaseConnection ;use PHPUnit \Framework \TestCase ;class DependencyInjectionTest extends TestCase { public function testDependencyInjection ( ) { $config = new DatabaseConfiguration ('localhost' , 3306 , 'domnikl' , '1234' ); $connection = new DatabaseConnection ($config ); $this ->assertEquals ('domnikl:1234@localhost:3306' , $connection ->getDsn ()); } }