当前位置:首页 > PHP教程 > php高级应用 > 列表

控制反转原则,它和依赖注入有什么联系

发布:smiling 来源: PHP粉丝网  添加日期:2022-07-23 09:54:47 浏览: 评论:0 

控制反转(IOC)

首先,我们来看一个例子。

  1. class Person 
  2.  
  3.  
  4.    private $name = ''
  5.  
  6.    private $age = 0; 
  7.  
  8.  
  9.  
  10.    public function __construct(string $name, int $age
  11.  
  12.    { 
  13.  
  14.        $this->name = $name
  15.  
  16.        $this->age = $age
  17.  
  18.    } 
  19.  
  20.  
  21.  
  22.    public function eat () 
  23.  
  24.    { 
  25.  
  26.        echo '吃东西' . PHP_EOL; 
  27.  
  28.    } 
  29.  
  30.  
  31.  
  32.    public function drink () 
  33.  
  34.    { 
  35.  
  36.        echo '喝水' . PHP_EOL; 
  37.  
  38.    } 
  39.  
  40.  
  41.  
  42.    public function sleep () 
  43.  
  44.    { 
  45.  
  46.        echo '睡觉' . PHP_EOL; 
  47.  
  48.    } 
  49.  
  50.  
  51.  
  52.    public function wakeup () 
  53.  
  54.    { 
  55.  
  56.        echo '起床' . PHP_EOL; 
  57.  
  58.    } 
  59.  
  60.  
  61.  
  62.    public function drive () 
  63.  
  64.    { 
  65.  
  66.        echo '开车' . PHP_EOL; 
  67.  
  68.    } 
  69.  
  70.  
  71.  
  72.    public function wash () 
  73.  
  74.    { 
  75.  
  76.        echo '洗漱' . PHP_EOL; 
  77.  
  78.    } 
  79.  

小明现在早上起来需要去上班,那么小明需要做以下事情

  1. $person = new Person('小明', 24); 
  2.  
  3. $person->wakeup(); 
  4.  
  5. $person->wash(); 
  6.  
  7. $person->eat(); 
  8.  
  9. echo '带上车钥匙、手机、电脑' .PHP_EOL; 
  10.  
  11. $person->drive(); 

上面的流程都是由程序员自己控制的。现在,我们想办法,让框架来控制流程。我们在Person类中新增一个方法,代码如下:

  1. public function work (callable $bring
  2.  
  3.  
  4.     $this->wakeup(); 
  5.  
  6.     $this->wash(); 
  7.  
  8.     $this->eat(); 
  9.  
  10.     $bring(); 
  11.  
  12.     $this->drive(); 
  13.  

小黄也需要去上班,现在他只安装框架的指导就可以完成上班的动作了。

  1. $person = new Person('小黄', 29); 
  2.  
  3. $person->work(function () 
  4.  
  5.  
  6.     echo '带上手机、车钥匙、文件' . PHP_EOL; 
  7.  
  8. }); 

修改后的代码完成了控制反转,以前的代码整个上班的流程由程序员控制,修改后的是由框架控制上班的流程的。程序的流程控制由程序员“反转”到了框架。

现在可以给出控制反转的定义了:

实际上,控制反转是一个比较笼统的设计思想,并不是一种具体的实现方法,一般用来指导框架层面的设计。这里所说的“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员“反转”给了框架。

依赖注入

控制反转是一种设计思想,而依赖注入是一种具体的编码技巧,依赖注入是实现控制反转最常用的技巧。依赖注入看起来“高大上”,实际上非常容易理解和掌握。

那到底什么是依赖注入呢?我们用一句话来概括就是:不通过 new() 的方式在类内部创建依赖类对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类使用。

下面来看一个实例:

  1. interface Log 
  2.  
  3.  
  4.    function write (string $msg); 
  5.  
  6.  
  7.  
  8.  
  9. class TextLog implements Log 
  10.  
  11.  
  12.    public function __construct($dirname$txtname
  13.  
  14.    { 
  15.  
  16.        $this->makeDir($dirname); 
  17.  
  18.        $this->mkTxt($txtname); 
  19.  
  20.    } 
  21.  
  22.  
  23.  
  24.    private function makeDir (string $dirName) :void 
  25.  
  26.    { 
  27.  
  28.        // do something 
  29.  
  30.    } 
  31.  
  32.  
  33.  
  34.    private function mkTxt (string $txtName) :void 
  35.  
  36.    { 
  37.  
  38.        // do something 
  39.  
  40.    } 
  41.  
  42.  
  43.  
  44.    public function write (string $msg
  45.  
  46.    { 
  47.  
  48.        // do something 
  49.  
  50.    } 
  51.  
  52.  
  53.  
  54.  
  55. class RedisLog implements Log 
  56.  
  57.  
  58.    private $redis = null; 
  59.  
  60.    private $key = ''
  61.  
  62.  
  63.  
  64.    public function __construct(string $key
  65.  
  66.    { 
  67.  
  68.        $this->redis = '...'// 获取redis实例 
  69.  
  70.        $this->key = $key
  71.  
  72.        // ... 
  73.  
  74.    } 
  75.  
  76.  
  77.  
  78.    public function write (string $msg
  79.  
  80.    { 
  81.  
  82.        // do something 
  83.  
  84.    } 
  85.  
  86.  
  87.  
  88.  
  89. class App 
  90.  
  91.  
  92.    public function run () 
  93.  
  94.    { 
  95.  
  96.        // do something 
  97.  
  98.  
  99.  
  100.        // 记录日志 
  101.  
  102.        (new RedisLog('log'))->write('框架运行信息记录'); 
  103.  
  104.    } 
  105.  

可以看到,App类依赖RedisLog类,如果我们今后不再使用redis来记录日子,而改用文本文件的话,那么就需要修改run里面的代码。

现在,我们换成使用依赖注入这种技巧来改写,代码如下;

  1. class App 
  2.  
  3.  
  4.    private $logHandle = null; 
  5.  
  6.  
  7.  
  8.    public function __construct(Log $log
  9.  
  10.    { 
  11.  
  12.        $this->logHandle = $log
  13.  
  14.    } 
  15.  
  16.  
  17.  
  18.    public function run () 
  19.  
  20.    { 
  21.  
  22.        // do something 
  23.  
  24.  
  25.  
  26.        // 记录日志 
  27.  
  28.        $this->logHandle->write('框架运行信息记录'); 
  29.  
  30.    } 
  31.  

改写后的App类不再依赖RedisLog类,可以随时换成其他的Log类,只要该类实现了write方法即可。可以看到,使用了依赖注入,可以灵活的替换掉所依赖的类,另外它是编写可测试代码最有效的手段。

Tags: php依赖注入

分享到: