Laravel 服务容器,IoC,DI
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的更多相关文章
- laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式
		
laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...
 - Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
		
容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...
 - laravel服务容器
		
laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...
 - laravel服务容器 转
		
laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...
 - Laravel 服务容器、服务提供器、契约实例讲解
		
前言 刚开始看laravel服务容器.契约.服务提供器的确生涩难懂,不单单是概念繁多,而且实际的demo很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道, ...
 - Laravel服务容器的绑定与解析
		
本篇文章给大家带来的内容是关于Laravel服务容器的绑定与解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 老实说,第一次老大让我看laravel框架手册的那天早上,我 ...
 - 关于使用 Laravel 服务容器的优势介绍
		
如果说laravel框架的核心是什么,那么无疑是服务容器.理解服务容器的概念,对于我们使用laravel太重要了,应该说是否理解服务容器的概念是区分是否入门laravel的重要条件.因为整个框架正是在 ...
 - laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)
		
首先大家想一想什么是容器,字面意思就是盛放东西的东西,常见的变量,对象属性都是容器,一个容器能够装什么东西,完全在于你对这个容器的定义.有的容器不仅仅只是存文本,变量,而是对象,属性,那么我们通过这种 ...
 - 依赖注入(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 ...
 
随机推荐
- Asp.Net WebApi 使用OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联(No OWIN authentication manager is associated with the request)” 异常的解决办法
			
在Asp.Net WebApi 项目中使用OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. ...
 - 多线程学习笔记-深入理解ThreadPoolExecutor
			
java多线程中,线程池的最上层接口是Executor,ExecutorService实现了Executor,是真正的管理线程池的接口,ThreadPoolExecutor间接继承了ExecutorS ...
 - auth模块用户认证
			
一.auth模块什么 auth模块时django自带的用户认证模块 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功 ...
 - centos 6.8 搭建svn服务器
			
1. yum remove subversion #卸载 svn服务 2.下载svn服务器安装包 yum -y install subversion 3.创建SVN版本库 mkdir -p /opt/ ...
 - Static Sushi AtCoder - 4118 (技巧枚举)
			
Problem Statement "Teishi-zushi", a Japanese restaurant, is a plain restaurant with only o ...
 - Kuro and Walking Route CodeForces - 979C (树上DFS)
			
Kuro is living in a country called Uberland, consisting of nn towns, numbered from 11to nn, and n−1n ...
 - Linux命令1
			
1.获取当前系统支持的所有命令的列表: compgen -c 2.怎样查看一个linux命令的概要与用法: whatis grep #便可查到grep的用法 3.怎样一页一页地查看一个大文件的内 ...
 - SpringBoot整合Sqlite数据库流程
			
1.创建项目 方式一: 通过网站https://start.spring.io/ 方式二: 通过开发工具(IDEA或者Eclipse自行百度) 2.修改pom.xml配置文件,添加必要的驱动包 < ...
 - c提高第三次作业
			
1. char buf[] = "abcdef"; //下面有啥区别? const char *p = buf; //p指向的内存不能变 char const *p = buf; ...
 - JQuery的Ajax技术
			
jquery是一个优秀的js框架,自然对js原生的ajax进行了封装, 封装后的ajax的操作方法更简洁,功能更强大,与ajax操作 相关的jquery方法有如下几种: Ajax 请求 $.ajax( ...