DI

DI 就是常说的依赖注入,那么究竟什么是依赖注入呢?

打个比方,电脑(非笔记本哈)需要键盘和鼠标我们才能进行操作,这个‘需要’换句话说就是‘依赖’键盘和鼠标。

那么,相应的,一个类需要另一个类才能进行作业,那么这也就是依赖。

看一段代码:

class Computer {
protected $keyboard; public function __construct() {
$this->$keyboard = new Keyboard();
}
}
// 这里的Computer类依赖了键盘类。

好,既然我们已经知道了什么是依赖,那么什么是注入呢?

我们改造一下上面的代码:

class Computer {
protected $keyboard; public function __construct(Keyboard $keyboard) {
$this->$keyboard = $keyboard;
}
} $computer = new Computer(new Keyboard()); //这里的Computer类依赖注入了Keyboard类。

其实依赖注入就是:所需要的类通过参数的形式传入的就是依赖注入。

理解了依赖注入,我们可以接着理解 IOC。

IOC

IOC 是什么呢?

中文叫控制反转。啥意思呢? 这个看明白了 DI 后就能很容易的理解了。

通过 DI 我们可以看到,一个类所需要的依赖类是由我们主动实例化后传入类中的。

控制反转和这个有什么关系呢?控制反转意思是说将依赖类的控制权交出去,由主动变为被动。

看一段 laravel 代码:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SessionController extends Controller
{ public function login(Request $request)
{
//这就是IOC,我们不需要主动传入类了一切由laravel去实现
}
}

看到这你可能有疑问了,这是怎么实现的呢?

这就是靠服务容器了,请往下接着看。

服务容器

服务容器其实就是一种设计模式,它的目的就是解耦依赖。

这里我们再从头至尾的看一遍,怎么一步步演化出服务容器。

依然是电脑的例子,我们知道电脑依赖键盘鼠标,可是键盘鼠标也有很多种呀。

先看一个最原始的代码例子:

class Computer {
protected $keyboard; public function __construct($type = null) { switch($type) {
case 'common':
return new CommonKeyboard();
case 'awesome':
return new AweSomeKeyboard();
default:
return new Keyboard();
} }
}

或许你一眼就看出了问题在哪。

如果我们又要增加一钟键盘,那我们又得对这个类进行修改。这样下去,这个类会变得庞大且耦合程度过高。

那么我们可以怎么修改呢?

  • 工厂模式

这样我们可以避免直接的修改 Computer 类。

class Factory {

        public static function getInstance($type){
switch($type) {
case 'common':
$this->keyboard = new CommonKeyboard();
break;
case 'awesome':
$this->keyboard = new AweSomeKeyboard();
break;
default:
$this->keyboard = new Keyboard();
break;
}
}
} class Computer {
protected $keyboard; public function __construct($type == null) {
$this->keyboard = Factory::getInstance($type);
}
}

这样使用简单工厂模式后,我们后续的修改可以不用对 Computer 类进行操作而只要修改工厂类就行了。这就相当于对 Computer 类进行了解耦。

Computer 类虽不在依赖那些键盘类了,但是却变为依赖工厂类了。

后续添加新类型的键盘就必须对工厂类进行修改。

所以这个工厂类还不能很好的满足要求,我们知道电脑对键盘的接口都是一致的,键盘必须实现这一接口才能被电脑识别,那我们对 Computer 和 Keyboard 类进行修改。

  • DI(依赖注入)
 interface Board {
public function type();
} class CommonBoard implements Board {
public function type(){
echo '普通键盘';
}
} class MechanicalKeyboard implements Board {
public function type(){
echo '机械键盘';
}
} class Computer {
protected $keyboard; public function __construct (Board $keyboard) {
$this->keyboard = $keyboard;
}
} $computer = new Computer(new MechanialKeyBoard());

可是这样也有问题,如果我们后续对这台电脑使用的键盘不满意要进行替换呢? 我们又回到原点了,必须去修改传入的键盘类。

能不能做成可配置的呢?

  • IOC 服务容器(超级工厂)
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);
}
}

这就是一个简单的 IOC 服务容器。

这个怎么解决我们上述的问题呢?

 $container = new Container;

    $container->bind('Board', function($container){
return new CommonBoard;
}); $container->bind('Computer',function($container,$module){
return new Computer($container->make($module));
}); $computer = $container->make('Computer',['Board']);

这里生产出来的 Computer 类就是一个使用普通键盘的电脑类了。

解释一下代码:

bind(name,function($container){
return new Name;
}) //这里的name和Name之间的关系是:
//当我需要name类的时候你就给我实例化Name类。 make(name)方法是对name进行生产返回一个实例。

如果我们要更换键盘怎么办呢?

$container->bind('Board', function($container){
return new MechanicalBoard;
}); $container->bind('Computer',function($container,$module){
return new Computer($container->make($module));
}); $computer = $container->make('Computer',['Board']);

只要对 bind 绑定的 Board 类的实现进行修改,我们就可以很容易替换掉键盘了。这就是一个服务容器。

参考

Laravel 服务容器,IoC,DI的更多相关文章

  1. laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式

    laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...

  2. Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)

    容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...

  3. laravel服务容器

    laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...

  4. laravel服务容器 转

    laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...

  5. Laravel 服务容器、服务提供器、契约实例讲解

        前言 刚开始看laravel服务容器.契约.服务提供器的确生涩难懂,不单单是概念繁多,而且实际的demo很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道, ...

  6. Laravel服务容器的绑定与解析

    本篇文章给大家带来的内容是关于Laravel服务容器的绑定与解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言   老实说,第一次老大让我看laravel框架手册的那天早上,我 ...

  7. 关于使用 Laravel 服务容器的优势介绍

    如果说laravel框架的核心是什么,那么无疑是服务容器.理解服务容器的概念,对于我们使用laravel太重要了,应该说是否理解服务容器的概念是区分是否入门laravel的重要条件.因为整个框架正是在 ...

  8. laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)

    首先大家想一想什么是容器,字面意思就是盛放东西的东西,常见的变量,对象属性都是容器,一个容器能够装什么东西,完全在于你对这个容器的定义.有的容器不仅仅只是存文本,变量,而是对象,属性,那么我们通过这种 ...

  9. 依赖注入(DI)与服务容器(IoC)

    参考文章:http://www.yuansir-web.com/2014/03/20/%E7%90%86%E8%A7%A3php-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A ...

随机推荐

  1. Lepus搭建企业级数据库慢查询分析平台

    前言 Lepus的慢查询分析平台是独立于监控系统的模块,该功能需要使用percona-toolkit工具来采集和记录慢查询日志,并且需要部署一个我们提供的shell脚本来进行数据采集.该脚本会自动开启 ...

  2. ABP拦截器之UnitOfWorkRegistrar(一)

    ABP中UnitOfWorkRegistrar拦截器是整个ABP中非常关键的一个部分,这个部分在整个业务系统中也是用的最多的一个部分,这篇文章的主要思路并不是写如何使用ABP中的UnitOfWork, ...

  3. jvm学习一:类加载过程详解

    (自学笔记,持续更新,欢迎指正) 我们都知道一个java程序运行要经过编译和执行,但是这太概括了,中间还有很多步骤,今天来说说类加载 学完类加载之后,java运行过程就可以分为  编译  > 类 ...

  4. 合并K个有序数组(链表)【字节跳动面试算法题】

    本题是本人字节跳动一面考的算法题原题是有序数组,一时没想到怎么解决数组的问题,但是如果给的是有序链表数组,则可以用下面的方法解决 可以利用最小堆完成,时间复杂度是O(nklogk),具体过程如下: 创 ...

  5. kafka相关问题集锦

    参考地址:https://blog.csdn.net/gao23191879/article/details/80815078?utm_source=blogxgwz5 你在写java 版的 kafk ...

  6. Django自带的用户认证auth模块

    一.介绍 基本上在任何网站上,都无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能. 使用Django,我们可以不需要自己写这些功能,因为Dj ...

  7. [BZOJ 4817] [SDOI 2017] 树点涂色

    Description Bob有一棵 \(n\) 个点的有根树,其中 \(1\) 号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点 ...

  8. JavaScript- BOM, DOM

    BOM Browser Object Model 浏览器对象模型, 提供与浏览器窗口进行交互的方法 它使 JavaScript 有能力与浏览器进行“对话”. BOM 最主要的对象就是 window 对 ...

  9. meta标签补充属性(viewport)

    我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的head标签中: <meta name="viewport" content="widt ...

  10. nginx启用status状态页

    nginx和php-fpm一样都内建了一个状态页,通过查看状态页信息可以连接到nginx服务负载情况,还可以利用状态页信息配zabbix监控,这里先介绍nginx的status状态页的使用. stau ...