2.6. 依赖注入
2.6.1. 目的
实现了松耦合的软件架构,可得到更好的测试,管理和扩展的代码
2.6.2. 用例
通过配置需要注入的依赖,Connection
能从 $config
中获取到所有它需要的依赖。如果没有依赖注入,Connection
会直接创建它需要的依赖,这样不利于测试和扩展 Connection
。
2.6.3. 例子
Doctrine2 ORM 使用了依赖注入,它通过配置注入了
Connection
对象。为了达到方便测试的目的,可以很容易的通过配置创建一个mock的Connection
对象。many frameworks already have containers for DI that create objects via a configuration array and inject them where needed (i.e. in Controllers)
2.6.4. UML 图

2.6.5. 代码
你可以在 GitHub 上找到这些代码
DatabaseConfiguration.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\DependencyInjection;
6
7class DatabaseConfiguration
8{
9 public function __construct(
10 private string $host,
11 private int $port,
12 private string $username,
13 private string $password
14 ) {
15 }
16
17 public function getHost(): string
18 {
19 return $this->host;
20 }
21
22 public function getPort(): int
23 {
24 return $this->port;
25 }
26
27 public function getUsername(): string
28 {
29 return $this->username;
30 }
31
32 public function getPassword(): string
33 {
34 return $this->password;
35 }
36}
DatabaseConnection.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\DependencyInjection;
6
7class DatabaseConnection
8{
9 public function __construct(private DatabaseConfiguration $configuration)
10 {
11 }
12
13 public function getDsn(): string
14 {
15 // this is just for the sake of demonstration, not a real DSN
16 // notice that only the injected config is used here, so there is
17 // a real separation of concerns here
18
19 return sprintf(
20 '%s:%s@%s:%d',
21 $this->configuration->getUsername(),
22 $this->configuration->getPassword(),
23 $this->configuration->getHost(),
24 $this->configuration->getPort()
25 );
26 }
27}
2.6.6. 测试
Tests/DependencyInjectionTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\DependencyInjection\Tests;
6
7use DesignPatterns\Structural\DependencyInjection\DatabaseConfiguration;
8use DesignPatterns\Structural\DependencyInjection\DatabaseConnection;
9use PHPUnit\Framework\TestCase;
10
11class DependencyInjectionTest extends TestCase
12{
13 public function testDependencyInjection()
14 {
15 $config = new DatabaseConfiguration('localhost', 3306, 'user', '1234');
16 $connection = new DatabaseConnection($config);
17
18 $this->assertSame('user:1234@localhost:3306', $connection->getDsn());
19 }
20}