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. NetSec2019 20165327 Exp7 网络欺诈防范

    NetSec2019 Exp7 网络欺诈防范 一.本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 (1)简单应用SET工具建立冒名网站 (1分) (2)ette ...

  2. windows下安装和使用scrapy

    首先,要确保已经正确安装了python环境,并安装了pip包 接着,打开cmd或者powershell ,输入命令 pip install scrapy .安装完之后 运行scrapy性能测试命令: ...

  3. Linux静态库与动态库制作过程

    文件:tobigchar.c   mian.c   tobigchar.h //tobigchar.c char tos() { char ch; ch = getchar(); if(ch > ...

  4. 删除 node_modules文件夹cmd指令

    方法一: npm install rimraf -g rimraf node_modules 方法二: rmdir /s/q your_app_dir 方法三: rm -f /node_modules

  5. python xlwt模块生成excel文件并写入数据 xlrd读取数据

    python中一般使用 xlwt (excel write)来生成Excel文件(可以控制单元格格式),用 xlrd 来读取Excel文件,用xlrd读取excel是不能对其进行操作的. 1.xlrd ...

  6. JS-JAVASCRIPT的eval()方法

    Lodop的传统模版是JS语句,如果储存的这种JS模版,可用javascript的eval()方法获取,该方法属于JS的范畴,并不是lodop语句,由于这个方法很多程序员可能不常用,对于这个JS方法不 ...

  7. socket之黏包

    一.黏包成因 1.tcp协议的拆包机制 当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去. MTU是Maximum Transmission Unit的缩写.意思 ...

  8. [powershell] 批量重命名,修改文件名中的部分字符串

    实例:替换一个目录下所有的字幕文件从720p到1080p ls $Path -Recurse |ForEach-Object{Rename-Item $_.FullName $_.FullName.R ...

  9. Python【第五篇】模块、包、常用模块

    一.模块(Module) 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文 ...

  10. 自动化运维工具Ansible介绍

    一个由 Python 编写的强大的配置管理解决方案.尽管市面上已经有很多可供选择的配置管理解决方案,但他们各有优劣,而 ansible 的特点就在于它的简洁. 让 ansible 在主流的配置管理系统 ...