服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|R语言|

服务器之家 - 编程语言 - PHP教程 - PHP依赖注入容器知识点浅析

PHP依赖注入容器知识点浅析

2021-09-27 11:39silencement PHP教程

在本篇文章里小编给大家分享的是一篇关于PHP依赖注入容器知识点内容,有兴趣的朋友们可以学习下。

依赖注入容器理解

耦合

一个好的代码结构设计一定是松耦合的,这也是很多通用设计模式的宗旨,就是把分散在各处的同一个功能的代码汇聚到一起,形成一个模块,然后在不同模块之间通过一些细小的、明确的渠道进行沟通。

在实践中,不同功能和模块之间的互相依赖是不可避免的,而如何处理好这些依赖之间的关系则是代码结构能否变得美好的关键。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php
 
class User
 
{
 
  public function register($user)
 
  {
 
    // 注册操作
 
    ...
 
 
 
    // 发送确认邮件
 
    $notify = new Notify();
 
    $notify->sendEmail('register', $user);
 
  }
 
}
 
 
 
class Notify
 
{
 
  public function sendEmail($type, $data)
 
  {
 
    switch $type {
 
      case 'register':
 
        // 发送注册确认邮件
 
        $email = new Email($type);
 
        $email->send($data);
 
      ...
 
    }
 
  }
 
}
 
 
 
class Email
 
{
 
  public function send($data)
 
  {
 
    // 发送邮件
 
  }
 
}

上述代码中,三个类之间逐层依赖,三个类实例化的顺序是 User -> Notify -> Email

也就是说我先实例化User类,可能执行了一些代码之后再去实例化我需要的其他类,比如Notify,以此类推。

这种依赖会让我们不得不为了得到需要的依赖而去做的一些准备工作,有时候可能一个new操作还不够。而这部分工作就是所说的耦合,他会让一个独立功能的类不得不去关心一些和自己的主体功能没什么关系的操作。

解除一个类对其他类的依赖

要解决这个问题也很简单,我可以先实例化好Email类,然后再实例化Notify,然后把Email对象作为参数传给Notify,最后实例化User类,然后把Notify传进去。这就是所谓的依赖注入,可以看到这个过程中类实例化的顺序完全反过来了,先实例化被依赖的对象,而不是先实例化最终需要的对象,这是控制反转。

代码如下:

?
1
2
3
4
5
6
7
<?php
 
$email = new Email();
 
$notify = new Notify($email);
 
$user = new User($notify);

可以通过构造函数来注入需要的依赖,也可以用一些其他的方法。

用容器托管依赖

那又有新的问题,例子中只有三个类还好,那如果这个User类依赖Notify来发邮件,依赖Model来存数据库,依赖redis来缓存,这样固然把依赖关系转移到了类的外部,但还是会导致我只想实例化一下User的时候,却要手动做很多的准备工作,会让代码混乱。所以这个时候需要一个容器。而这个容器的作用就是替我来管理这些依赖。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
 
// 容器
 
class Container implements ArrayAccess
 
{
 
  protected $values = [];
 
 
 
  public function offsetGet($offset)
 
  {
 
    return $this->values[$offset]($this);
 
  }
 
 
 
  public function offsetSet($offset, $value)
 
  {
 
    $this->values[$offset] = $value;
 
  }
 
}

在程序启动的时候,我们可以在一个地方统一的注册好一系列的基础服务。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
 
$container = new Container();
 
 
 
$container['notify'] = function($c) {
 
  return new Notify();
 
};
 
 
 
$container['email'] = function($c) {
 
  return new Email();
 
};

就会变成这样

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
 
class User
 
{
 
  public function register($user)
 
  {
 
    // 注册操作
 
    ...
 
 
 
    // 发送确认邮件
 
    $container('notify')->sendEmail('register', $user);
 
  }
 
}
 
 
 
class Notify
 
{
 
  public function sendEmail($type, $data)
 
  {
 
    switch $type {
 
      case 'register':
 
        // 发送注册确认邮件
 
        $email = $container['email'];
 
        $email->send($data);
 
      ...
 
    }
 
  }
 
}
 
 
 
class Email
 
{
 
  public function send($data)
 
  {
 
    // 发送邮件
 
  }
 
}

就是当User需要Notify的时候,会去向容器要这个类的对象,那至于Notify再依赖什么其他的东西,我就不用管了,因为Notify也会去向容器要它自己需要的依赖。所有这些依赖关系的处理就完全托管给容器了,我们既不需要去关心依赖之间的层次关系,也避免了依赖之间的耦合。

需要注意的是,依赖注入容器一般只接受一个匿名函数,而不是一个实例化好的对象,匿名函数会告诉容器怎样去获得一个对象,这样可以使得一个服务在被需要的时候才会去实例化

以上就是本次介绍的全部相关知识点,感谢大家的学习和对服务器之家的支持。

原文链接:https://www.php.cn/php-ask-441719.html

延伸 · 阅读

精彩推荐
  • PHP教程php操作mongodb封装类与用法实例

    php操作mongodb封装类与用法实例

    这篇文章主要介绍了php操作mongodb封装类与用法,结合具体实例形式分析了php定义的MongoDB操作封装类与相关的类实例化、查询、更新等使用技巧,需要的朋友可...

    攻城狮的梦4482019-09-09
  • PHP教程20个2020年最优秀的PHP框架回顾

    20个2020年最优秀的PHP框架回顾

    这篇文章主要介绍了20个2020年最优秀的PHP框架回顾,简单分析了目前比较主流的优秀框架供大家参考,需要的朋友可以参考下 ...

    PHP教程网8502020-08-01
  • PHP教程PHP实现执行外部程序的方法详解

    PHP实现执行外部程序的方法详解

    这篇文章主要介绍了PHP实现执行外部程序的方法,结合实例形式分析了php执行外部程序的常用函数相关使用技巧与注意事项,需要的朋友可以参考下...

    Jackwoo6442021-06-18
  • PHP教程php cli模式下获取参数的方法

    php cli模式下获取参数的方法

    本篇文章主要介绍了php cli模式下获取参数的方法,具有很好的参考价值。下面跟着小编一起来看下吧...

    傲雪星枫7562021-05-16
  • PHP教程THINKPHP在添加数据的时候获取主键id的值方法

    THINKPHP在添加数据的时候获取主键id的值方法

    下面小编就为大家带来一篇THINKPHP在添加数据的时候获取主键id的值方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看...

    PHP教程网5852021-05-07
  • PHP教程Apache中php.ini的设置方法

    Apache中php.ini的设置方法

    无论是IIS 还是 Apache, 在启动PHP的时候,默认都从系统变量"C:\Windows"这个目录中寻找。 如果要在系统中同时使用IIS和Apache来运行PHP,而且PHP的版本又不一样...

    PHP教程网2242020-03-12
  • PHP教程PHP排序算法类实例

    PHP排序算法类实例

    这篇文章主要介绍了PHP排序算法类,实例分析了插入排序、选择排序、冒泡排序、快速排序等排序算法的原理与实现技巧,需要的朋友可以参考下...

    邪恶的小Y2742020-09-29
  • PHP教程PHP基于SPL实现的迭代器模式示例

    PHP基于SPL实现的迭代器模式示例

    这篇文章主要介绍了PHP基于SPL实现的迭代器模式,简单描述了迭代器模式的概念、原理并结合实例形式分析了php使用SPL实现迭代器模式的相关操作技巧与注意...

    LSGOZJ5492019-10-11