依賴注入(Dependence Injection, DI) 依賴注入是控制反轉的一種設計模式。依賴注入的核心是把類所依賴的單元的實例化過程,放到類的外面去實現。依賴注入的實現離不開反射。
依賴注入(Dependence Injection, DI)
所謂的依賴注入,指將依賴的對象通過參數的形式一次性傳入,使用時不需要顯式 new
了,比如把A類所依賴的B類、C類等以屬性或者構造函數等方式注入A類而不是直接在A類中實例化。
只要不是由內部生產(比如初始化、構造函數中通過工廠方法、自行手動 new 的),而是由外部以參數或其他形式注入的,都屬於依賴注入(DI) 。
依賴注入需要利用反射實現,比如:
class A
{
protected $b;
public function __constrcut(B $b)
{
$this->b = $b;
}
}
// 通過控制反轉容器生成 A 的實例時,會通過反射發現 A 的構造函數需要一個 B 類的實例
// 於是自動向 A 類的構造函數注入 B 類的實例
$a = IoC::make(A::class);
依賴注入的實質就是把一個類不可更換的部分
和可更換的部分
分離開來,通過注入
的方式來使用,從而達到解耦的目的。
比如有一個 Mysql
數據庫連接類如下:
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 = 'db';
}
public function connect()
{
return mysqli_connect($this->host,$this->username ,$this->password,$this->db_name,$this->port);
}
}
// 使用
$db = new Mysql();
$con = $db->connect();
可更換部分是數據庫的配置
class Configuration
{
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;
}
}
不可更換部分是Mysql數據庫的連接操作
class Mysql
{
private $configuration;
public function construct(DatabaseConfiguration $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());
}
}
這樣就完成了配置文件和連接邏輯的分離,使用如下:
$config = new Configuration('127.0.0.1', 'root', '', 'my_db', 22);
$db = new Mysql($config);
$con = $db->connect();
$config是注入Mysql的,這就是所謂的依賴注入。
總結
注入可以理解成從外面把東西打進去。因此,依賴注入模式中,要分清內和外,要解除依賴的類內部就是內,實例化所依賴單元的地方就是外。在外通過構造形參,爲類內部的抽象單元提供實例化,達到解耦的目的,使下層依賴於上層,而不是上層依賴於下層。
因此,依賴注入模式中,要用對象傳遞,通過一個實例的反射來實現,這是數組做不到的。