PHP 依赖注入 (DI)


什么是 依赖注入

DI(Dependency Injection 依赖注入)是IOC的一种实现,表现为:在类A的实例创建过程中即创建了依赖的B对象,通过类型或名称来判断将不同的对象注入到不同的属性中。

依赖注入是对于要求更易维护,更易测试,更加模块化的代码的解决方案。

实现方式

  • 构造器注入 ( constructor 注入)

    通过构造函数传递依赖。构造函数的参数必然用来接收一个依赖对象。构造函数的参数应该是一个抽象类型。

    $book = new Book($databaseConnection, $configFile);
  • 属性注入 (setter 注入)

    属性注入是通过属性来传递依赖。

    $book = new Book();
    $book->setDatabase($databaseConnection);
    $book->setConfigFile($configFile);
  • 接口注入

    先定义一个接口,包含一个设置依赖的方法。然后依赖类,继承并实现这个接口。

为什么使用

  • 不必自己在代码中维护对象的依赖
  • 容器自动根据配置,将依赖注入指定对象

使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

与IoC关系 ^2

IoC

如何实现 依赖注入 ^1

  • 没有使用容器

    <?php
    
    class Foo
    &#123;
        protected $_bar;
        protected $_baz;
    
        public function __construct(Bar $bar, Baz $baz) &#123;
            $this->_bar = $bar;
            $this->_baz = $baz;
        &#125;
    &#125;
    
    // In our test, using PHPUnit's built-in mock support
    $bar = $this->getMock('Bar');
    $baz = $this->getMock('Baz');
    
    $testFoo = new Foo($bar, $baz);
  • 使用容器

    <?php
    
    // In our test, using PHPUnit's built-in mock support
    $container = $this->getMock('Container');
    $container['bar'] = $this->getMock('Bar');
    $container['baz'] = $this->getMock('Baz');
    
    $testFoo = new Foo($container['bar'], $container['baz']);

Service Locator 的区别 ^1

<?php

class Foo
&#123;
    protected $_bar;
    protected $_baz;

    public function __construct(Container $container) &#123;
        $this->_bar = $container['bar'];
        $this->_baz = $container['baz'];
    &#125;
&#125;

// In our test, using PHPUnit's built-in mock support
$container = $this->getMock('Container');
$container['bar'] = $this->getMock('Bar');
$container['baz'] = $this->getMock('Bar');

$testFoo = new Foo($container);

判断 Dependency Injection 和 Service Locator 区别的关键是在哪使用容器:

  • 如果在非工厂对象的外面使用容器,那么就属于 Dependency Injection。
  • 如果在非工厂对象的内部使用容器,那么就属于 Service Locator。

参考文档


Author: Itaken
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Itaken !
  TOC目录