PHP 依赖注入模式
目的
实现了松耦合的软件架构,可得到更好的测试,管理和扩展的代码
用例
通过配置需要注入的依赖,Connection 能从 $config 中获取到所有它需要的依赖。如果没有依赖注入,Connection 会直接创建它需要的依赖,这样不利于测试和扩展 Connection。
例子
- Doctrine2 ORM 使用了依赖注入,它通过配置注入了 Connection 对象。为了达到方便测试的目的,可以很容易的通过配置创建一个mock的 Connection 对象。
许多框架已经有用于DI的容器,这些容器通过配置数组创建对象,并在需要的地方(即在控制器中)注入它们。
UML 图
代码
DatabaseConfiguration.php
<?php declare(strict_types=1); namespace DesignPatterns\Structural\DependencyInjection; class DatabaseConfiguration { public function __construct( private string $host, private int $port, private string $username, private string $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
<?php declare(strict_types=1); namespace DesignPatterns\Structural\DependencyInjection; class DatabaseConnection { public function __construct(private DatabaseConfiguration $configuration) { } public function getDsn(): string { // this is just for the sake of demonstration, not a real DSN // notice that only the injected config is used here, so there is // a real separation of concerns here return sprintf( '%s:%s@%s:%d', $this->configuration->getUsername(), $this->configuration->getPassword(), $this->configuration->getHost(), $this->configuration->getPort() ); } }
测试
Tests/DependencyInjectionTest.php
<?php declare(strict_types=1); 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->assertSame('domnikl:1234@localhost:3306', $connection->getDsn()); } }