依赖注入

当A类需要依赖于B类,也就是说需要在A类中实例化B类的对象来使用时候,如果B类中的功能发生改变,也会导致A类中使用B类的地方也要跟着修改,导致A类与B类高耦合。这个时候解决方式是,A类应该去依赖B类的接口,把具体的类的实例化交给外部。

就拿我们业务中常用的通知模块来说。

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

<?php

/**

 * 定义了一个消息类

 * Class Message

 */

class  Message{

  public function seed()

  {

      return 'seed email';

  }

}

/*

 * 订单产生的时候 需要发送消息

 */

class Order{

    protected $messager = '';

    function __construct()

    {

        $this->messager = new Message();

    }

    public function seed_msg()

    {

        return $this->messager->seed();

    }

}

$Order = new Order();

$Order->seed_msg();

上面的代码是我们传统的写法。首先由个消息发送的类。然后在我们需要发送消息的地方,调用发送消息的接口。有一天你需要添加一个发送短信的接口以满足不同的需求。那么你会发现你要再Message类里面做修改。同样也要再Order类里面做修改。这样就显得很麻烦。这个时候就有了依赖注入的思路。下面把代码做一个调整

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

<?php

/**

 * 为了约束我们先定义一个消息接口

 * Interface Message

 */

interface  Message{

  public function seed();

}

/**

 * 有一个发送邮件的类

 * Class SeedEmail

 */

class SeedEmail implements Message

{

    public function seed()

    {

        return  'seed email';

        // TODO: Implement seed() method.

    }

}

/**

 *新增一个发送短信的类

 * Class SeedSMS

 */

class SeedSMS implements Message

{

    public function seed()

    {

        return 'seed sms';

        // TODO: Implement seed() method.

    }

}

/*

 * 订单产生的时候 需要发送消息

 */

class Order{

    protected $messager = '';

    function __construct(Message $message)

    {

        $this->messager = $message;

    }

    public function seed_msg()

    {

        return $this->messager->seed();

    }

}

//我们需要发送邮件的时候

$message = new SeedEmail();

//将邮件发送对象作为参数传递给Order

$Order = new Order($message);

$Order->seed_msg();

//我们需要发送短信的时候

$message = new SeedSMS();

$Order = new Order($message);

$Order->seed_msg();

这样我们就实现了依赖注入的思路,是不是很方便扩展了。

服务容器

我理解的服务容器就是一个自动产生类的工厂。

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

70

<?php

/**

 * 为了约束我们先定义一个消息接口

 * Interface Message

 */

interface  Message{

    public function seed();

}

/**

 * 有一个发送邮件的类

 * Class SeedEmail

 */

class SeedEmail implements Message

{

    public function seed()

    {

        return  'seed email';

        // TODO: Implement seed() method.

    }

}

/**

 *新增一个发送短信的类

 * Class SeedSMS

 */

class SeedSMS implements Message

{

    public function seed()

    {

        return 'seed sms';

        // TODO: Implement seed() method.

    }

}

/**

 * 这是一个简单的服务容器

 * Class Container

 */

class Container

{

    protected $binds;

    protected $instances;

    public function bind($abstract, $concrete)

    {

        if ($concrete instanceof Closure) {

            $this->binds[$abstract] = $concrete;

        } else {

            $this->instances[$abstract] = $concrete;

        }

    }

    public function make($abstract, $parameters = [])

    {

        if (isset($this->instances[$abstract])) {

            return $this->instances[$abstract];

        }

        array_unshift($parameters, $this);

        return call_user_func_array($this->binds[$abstract], $parameters);

    }

}

//创建一个消息工厂

$message = new  Container();

//将发送短信注册绑定到工厂里面

$message->bind('SMS',function (){

     return   new  SeedSMS();

});

//将发送邮件注册绑定到工厂

$message->bind('EMAIL',function (){

   return new  SeedEmail();

});

//需要发送短信的时候

$SMS  = $message->make('SMS');

$SMS->seed();

container是一个简单的服务容器里面有bind,make两个方法

bind是向容器中绑定服务对象。make则是从容器中取出对象。

bind

在bind方法中需要传入一个 concrete 我们可以传入一个实例对象或者是一个闭包函数。

可以看到我这全使用的是闭包函数,其实也可以这样写

1

2

$sms = new  SeedSMS();

$message->bind('SMS',$sms);

后面这种写法与闭包相比的区别就是我们需要先实例化对象才能往容易中绑定服务。而闭包则是我们使用这个服务的时候才去实例化对象。可以看出闭包是有很多的优势的。

make

make方法就从容器中出去方法。里面首先判断了instances变量中是否有当前以及存在的服务对象,如果有直接返回。如果没有那么会通过 call_user_func_array返回一个对象.

  明确的学习思路能更高效化的学习

点此加入该群学习

PHP中的服务容器与依赖注入的思想的更多相关文章

  1. AspectCore中的IoC容器和依赖注入

    IOC模式和依赖注入是近年来非常流行的一种模式,相信大家都不陌生了,在Asp.Net Core中提供了依赖注入作为内置的基础设施,如果仍不熟悉依赖注入的读者,可以看看由我们翻译的Asp.Net Cor ...

  2. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  3. IOC容器的依赖注入

    1.依赖注入发生的时间 当Spring IoC容器完成了Bean定义资源的定位.载入和解析注册以后,IoC容器中已经管理类Bean定义的相关数据,但是此时IoC容器还没有对所管理的Bean进行依赖注入 ...

  4. springboot成神之——ioc容器(依赖注入)

    springboot成神之--ioc容器(依赖注入) spring的ioc功能 文件目录结构 lang Chinese English GreetingService MyRepository MyC ...

  5. Spring中的控制反转和依赖注入

    Spring中的控制反转和依赖注入 原文链接:https://www.cnblogs.com/xxzhuang/p/5948902.html 我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达 ...

  6. ASP.NET中IOC容器Autofac(依赖注入DI 控制反转IOC)

    IOC的一个重点是在程序运行中,动态的向某个对象提供它所需要的其他对象.这一点是通过DI来实现的.Autofac则是比较流行的一款IOC容器. IoC和DI有什么关系呢?其实它们是同一个概念的不同角度 ...

  7. 通过中看不中用的代码分析Ioc容器,依赖注入....

    /** * 通过生产拥有超能力的超人实例 来理解IOC容器 */ //超能力模组接口 interface SuperModuleInterface{ public function activate( ...

  8. ABP+AdminLTE+Bootstrap Table权限管理系统第四节--仓储,服务,服务接口及依赖注入

    在ABP框架中,仓储,服务,这块算是最为重要一块之一了.ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块,一个程序集可看成一个模块, 一个模块可以通过一个类来定义这个模块,而给定义这 ...

  9. 简单理解laravel框架中的服务容器,服务提供者以及怎样调用服务

      laravel被称为最优雅的框架,最近正在学习中,对于用惯了thinkphp.ci框架的人来说,服务容器.服务提供者,依赖注入这些概念简直是一脸懵逼.我花了些时间梳理了一下,也不敢确定自己说的是对 ...

随机推荐

  1. 【Leetcode 做题学算法周刊】第一期

    首发于微信公众号<前端成长记>,写于 2019.10.28 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 1. ...

  2. 关闭ESlint 语法检测配置方法

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qappleh/article/detai ...

  3. 记录一次诡异的Maven Profile不生效的问题

    记录一次诡异的Maven Profile不生效的问题 现象 maven 打包之后,复制的 profile对应的resource文件总是不正确的. 即便是加了 mvn clean package -P ...

  4. spring-boot-plus V1.4.0发布 集成用户角色权限部门管理

    RBAC用户角色权限 用户角色权限部门管理核心接口介绍 Shiro权限配置

  5. AB实验的高端玩法系列3 - AB组不随机?观测试验?Propensity Score

    背景 都说随机是AB实验的核心,为什么随机这么重要呢?有人说因为随机所以AB组整体不存在差异,这样才能准确估计实验效果(ATE) \[ ATE = E(Y_t(1) - Y_c(0)) \] 那究竟随 ...

  6. MYSQL-LINUX 安装步骤

    https://www.cnblogs.com/dengshihuang/p/8029092.html   5.7版本安装步骤 1.官网下载mysql二进制文件,匹配自己的linux版本: wget ...

  7. 20191106-使用pyttsx对文本进行语音输出

    实现pyttsx文字转语音的开源库调用 参考: 1.  https://blog.csdn.net/liuyubo23/article/details/83990532 2.  https://www ...

  8. 20190730_图像混合_opencv_python

    今天学习了 图像的混合 教程上的代码很简单,但是绝对运行不出来 教程名称:OpenCV-Python 中文教程 #图像融合 import cv2 import numpy as np import m ...

  9. Python基本数据结构之集合

    一道python面试的一个小问题,说怎么使用一行代码将一个列表里的重复元素,其实这里只要将列表转换成集合就可以了. 定义 集合跟我们学的列表有点像,也是可以存一堆数据,不过它有几个独特的特点,令其在整 ...

  10. STL.h

    最近老是被系统的一些STL卡到飞起,然后就手打了一个STL.h 库函数还没有打完,以后打新的还会再更,大家也可以使用,顺便帮我找一下bug,然后我再改进! template< typename ...