初学依赖注入

学习了依赖注入,做一个记录.

一.概念

  1. 依赖倒置原则( Dependence Inversion Principle ,缩写为 DIP ),一种软件设计原则,是一个抽象的概念.
  2. 控制反转( Inversion of Control ,缩写为 IoC ),DIP 的一种具体实现方式.
  3. 依赖注入( Dependency injection ,缩写为 DI ),IOC 的具体实现方式.

什么是反转?对应的什么是正转?依赖谁?依赖什么?注入谁?注入什么?一个日常生活的例子,可以解惑:

  • 某人想开车,于是自己去造车,此时可以理解为控制正转,我想要车多大我就造多大,想要车是什么颜色就涂什么颜色.
  • 最后发现造车太难,于是选择去经销商买一辆车,可以理解为控制反转,经销商只提供蓝色的车,我就只能买蓝色的车,经销商控制了,依赖经销商注入

结论就是,造车难,买车容易,在写程序的时候使用依赖注入可以更好的解耦

二.自己造车

<?php
class Car
{
    //汽车可以跑,定义一个方法 run()
    public function run(){
        return '滴滴滴,车开了';
    }
}

class Person
{
    private $car = null;//保存某人的车,暂时还没车
    public function drive(){
        $this->car = new Car();//要开车先造车,造了一辆车保存在某人的 $car 里
        return $this->car->run();//调用车的 run() 方法
    }
}

$xiaoming = new Person();
echo $xiaoming->drive();//输出 滴滴滴,车开了

三.造车太难了(依赖注入)

<?php
class Car
{
    //汽车可以跑,定义一个方法 run()
    public function run()
    {
        return '滴滴滴,车开了';
    }
}

class Person
{
    private $car = null;//保存某人的车,暂时还没车

    //new 某人的时候,就给他注入一辆车,通过 $a 传入构造方法,并保存在 $car 里
    public function __construct($a)
    {
        $this->car = $a;
    }

    public function drive()
    {
        return $this->car->run();//调用车的 run() 方法
    }
}
$car  = new Car();//买一辆车
$xiaoming = new Person($car);//new 小明的时候,把刚才买的车注入
echo $xiaoming->drive();//输出 滴滴滴,车开了

万一new小明的时候,给他买了一架飞机,并注入,小明不会开飞机怎么办,通过类型限定解决这个问题

class Person
{
   .
   .
   .
    public function __construct(Car $a)// <----这里做类型限定,保证不会注入飞机,也不会注入火箭
    {
        $this->car = $a;
    }
    .
    .
    .

四.IoC 容器

在上例中,我们是手动的去 new 一辆车并注入给某人,现在用一个容器统一的去管理这些需要注入的类。

<?php
class Car
{
    //汽车可以跑,定义一个方法 run()
    public function run()
    {
        return '滴滴滴,车开了';
    }
}

class Person
{
    private $car = null;//保存某人的车,暂时还没车

    //new 某人的时候,就给他注入一辆车,通过 $a 传入构造方法
    public function __construct(Car $a)// <----这里做了类型限定
    {
        $this->car = $a;
    }

    public function drive()
    {
        return $this->car->run();//调用车的 run() 方法
    }
}

//写一个简单的 IoC 容器类
class Container{
    private static $objArr = [];//定义一个静态的空数组

    public static function set($flag, Callable $func){
        self::$objArr[$flag] = $func;//存入键值对,键是一个字符串,作为标识符,值是一个匿名函数
    }

    public static function get($flag){
        $tmp = self::$objArr[$flag];//取出标识符对应的匿名函数,用$tmp临时保存一下
        return $tmp();//在$tmp后名加上括号,表示执行这个函数,并返回
    }
}

//下面这条语句执行完毕后,会在 $objArr 里存入一个键值对,键是 car ,值是这个匿名函数,该匿名函数返回的是创建 Car 对象的语句
Container::set('Car', function(){
    return new Car();
});

//下面这条语句执行完毕后,会在 $objArr 里存入一个键值对,键是 person ,值是这个匿名函数,该匿名函数返回的是创建 Person 对象的语句
Container::set('Person', function(){
    return new Person(Container::get('Car'));//直接去容器中取一辆车出来,并作为参数传给 Person 类的构造函数
});

$xiaomin = Container::get('Person');//直接去容器中取一个人出来,取名叫小明
echo $xiaomin->drive();//输出 滴滴滴,车开了
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

感觉讲得很通俗易懂呀~~~哈哈,不过什么场景下用依赖注入会比较合适呢?自己造车那一段代码感觉是最浅显易懂的,用上了依赖注入之后感觉就不那么便于理解了

6年前 评论

@kevin2011 其实,我这个理解只是最基本的,就好像还停留在理论阶段,要真的运用在实际项目中,还需要更深入的学习.至于说运用场景,可以在任何时候,只要你想达到解耦的目的,就可以用,可是实际上这样的代码是无法用的,它的作用仅仅是帮助理解概念,在学习第一本书的的时候,我们已经不知不觉用了依赖注入,比如在 app/Http/Controllers/UsersController.php 文件中写过这样一段代码:

.
.
.
public function edit(User $user) //  <-----这里依赖框架给我们注入了一个 $user 对象
    {
        $this->authorize('update', $user);
        return view('users.edit', compact('user'));
    }
.
.
.
6年前 评论

滴,老司机卡

6年前 评论

讲的不错

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!