设计模式の结构型の依赖注入模式

很简单的理解

终于要讲到这个著名的设计原则,其实它比其他设计模式都简单。
依赖注入的实质就是把一个类不可能更换的部分 和 可更换的部分 分离开来,通过注入的方式来使用,从而达到解耦的目的。

一个数据库连接类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Mysql
{
private $host;
private $port;
private $username;
private $password;
private $db_name;

public function __construct()
{
$this->host = '127.0.0.1';
$this->port = 22;
$this->username = 'root';
$this->password = '';
$this->db_name = 'my_db';
}

public function connect()
{
return mysqli_connect($this->host, $this->username, $this->password, $this->db_name, $this->port);
}
}

使用

1
2
$db  = new Mysql();
$con = $db->connect();

通常应该设计为单例,这里就先不搞复杂了。

依赖注入

显然,数据库的配置是可以更换的部分,因此我们需要把它拎出来。

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
class MysqlConfiguration
{
private $host;
private $port;
private $username;
private $password;
private $db_name;

public function __construct(string $host, int $port, string $username, string $password, string $db_name)
{
$this->host = $host;
$this->port = $port;
$this->username = $username;
$this->password = $password;
$this->db_name = $db_name;
}

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;
}

public function getDbName(): string
{
return $this->db_name;
}
}

然后不可替换的部分这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Mysql
{
private $configuration;

public function __construct(MysqlConfiguration $config)
{
$this->configuration = $config;
}

public function connect()
{
return mysqli_connect($this->configuration->getHost(), $this->configuration->getUsername(), $this->configuration->getPassword, $this->configuration->getDbName(), $this->configuration->getPort());
}
}

这样就完成了配置文件和连接逻辑的分离。

使用

1
2
3
$config = new MysqlConfiguration('127.0.0.1', 'root', '', 'my_db', 22);
$db = new Mysql($config);
$con = $db->connect();

$config 是注入 Mysql 的,这就是所谓的依赖注入。

备注

还有一种做法就是将所有的组件都放在一个容器里,等到控制器需要的时候,再去动态注入进来,后续如果还要再使用的话,就从已经加载了的是实例中获取。