依赖注入

2018-05-03 Vaniot 更多博文 » 博客 » GitHub »

设计模式

原文链接 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;
    }
}

依赖注入的优缺点

优点

  • 解耦
  • 明确的了解组件间的依赖关系
  • 简化测试

缺点

组件与注入容器间不会存在依赖的关系,故而组件无法从注入器获得更多的服务,只有配置信息中的服务。