依赖注入

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

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

<?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类里面做修改。这样就显得很麻烦。这个时候就有了依赖注入的思路。下面把代码做一个调整

<?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();

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

服务容器

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

<?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 我们可以传入一个实例对象或者是一个闭包函数。

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

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

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

make

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

更多的PHP相关知识,请访问PHP中文网!

更多相关文章

  1. PHP创建对象的6种方式
  2. 如何直接访问php实例对象的private属性
  3. PHP字符逃逸导致的对象注入详解
  4. Pimple运行流程浅析(PHP容器)
  5. 一文搞懂PHP类和对象、抽象类、接口
  6. 在Docker容器中部署整套基于Spring Cloud的微服务架构,看这篇就对
  7. Github标星19K+Star,10分钟自建对象存储服务!
  8. 1.docker介绍安装,镜像管理,通过容器、模板创建镜像
  9. 2.docker容器管理、仓库管理、数据管理、数据卷备份恢复

随机推荐

  1. MySQL查询优化系列讲座之数据类型与效率
  2. 解析innodb status各项参数
  3. 如何使用java Web服务从mysql数据库获取
  4. 使用C#在MySQL中备份数据库
  5. Navicat工具备份还原mysql数据库详细图解
  6. navicat for mysql 连接报错1251详细解决
  7. Mysql基础之字符集与乱码
  8. Sqoop_详细总结 使用Sqoop将HDFS/Hive/HB
  9. 不知道有人在mysql5.0上 针对10亿条数据
  10. mysql中的隐式提交