依赖注入
原文链接 https://vaniot-s.github.io/2018/05/03/%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
在实现功能模块通常需要使用另外一个(或多个)组件(无法被当前使用者修改的功能模块)或服务(使用者通过同步或者异步请求的功能接口),依赖注入通过构造注入,允许代码从硬编码的依赖中解耦,使得在运行时或编译时可以修改的软件设计模式。
ps:组件在本地,服务在远程 <!--more-->
依赖注入的两种方式
<?php namespace database; class Database { protected $adapter; /**未使用依赖注入时,产生紧密的耦合**/ public function __construct() { $this->adapter=new MysqlAdapter; } }
class MysqlAdapter{}
#### 通过构造函数
```php
<?php
namespace database;
class Database
{
protected $adapter;
/**使用依赖注入重构,解耦**/
public function __construct(MysqlAdapter $adapter)
{
$this->adapter=$adapter;
}
}
class MysqlAdapter{}
通过setter设值
<?php
namespace database;
class Database
{
protected $adapter;
/**使用依赖注入重构,解耦**/
public function setAdapter(MysqlAdapter $adapter)
{
$this->adapter=$adapter;
}
}
class MysqlAdapter{}
ps:选择依赖注入的方式
选择通过构造函数注入:
- 能够在构造阶段就创建完整、合法的对象;
- 带有参数的构造子可以明确地告诉你如何创建一个合法的对象;
- 可以隐藏任何不可变的字段。
选择通过 setter 设值方法注入
- 如果依赖的「插件」太多时,选择设值注入更优
反转控制(Inversion of Control)
依赖的对象在系统的其他地方控制和实例化依赖对象,即系统通过组织控制和对象的完全分离来实现解耦。
依赖反转
依赖接口/约定或则抽象类,而不是具体实现即面向对象设计中的依赖倒置,提高代码的拓展性,实现相同的接口接口。
<?php
namespace Database;
class Database
{
protected $adapter;
/**依赖于接口,**/
public function __construct(AdapterInterface $adapter)
{
$this->adapter=$adapter;
}
}
//定义接口
interface AdapterInterface{}
//实现接口
class MysqlAdapter implements AdapterIntrface {}
class OricleAdapter implements AdapterInterface {}
容器
依赖注入容器是一个独立的模块完成依赖注入中类的实例化的工作。
class Container
{
public function getAdapter()
{
return new adapter();
}
public function getDatabase()
{
$database=new Database($this->getAdapter());
return $database;
}
}
依赖注入的优缺点
优点
- 解耦
- 明确的了解组件间的依赖关系
- 简化测试
缺点
组件与注入容器间不会存在依赖的关系,故而组件无法从注入器获得更多的服务,只有配置信息中的服务。