Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
126 lines (100 sloc) 4.15 KB

Laravel Inversion of Control (控制反转) 概念简介

本文内容部分摘自 Wikipedia - Inversion of Control .

概述

IoC (控制反转),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

实现「控制反转」,有两种方式:

  • Dependency Injection (DI) - 依赖注入
  • Dependency Lookup - 依赖查找

两者的区别在于,前者是被动的接收对象,在类实例创建过程中即创建了依赖的对象,通过类型或名称来判断将不同的对象注入到不同的属性中,而后者是主动索取相应类型的对象,获得依赖对象的时间也可以在代码中自由控制。

哪些方面的「控制」被「反转」了?

依赖对象的「获得」被反转了。

技能描述

Class A 中用到了 Class B 的对象 b,一般情况下,需要在 A 的代码中显式的 new 一个 B 的对象。采用依赖注入技术之后,A 的代码只需要定义一个私有的B对象,不需要直接 new 来获得这个对象,而是通过相关的 容器控制程序 来将 B 对象在外部 new 出来并注入到 A 类里的引用中。而具体获取的方法、对象被获取时的状态由 容器 来指定。

假设我有一个 iPhone,我的 iPhone 依赖充电器才能充电。

class iPhone
{
    // 电量
    private $power;

    // 充电
    public function charge()
    {
    }
}

我还有个苹果原装充电器:

class AppleCharger
{
    public function charge()
    {
        return 100;
    }
}

在以前,iPhone 内部「控制」着只能用哪一款充电器:

class iPhone
{
    // 电量
    private $power;

    // 充电,只能用原装的充电器
    public function charge()
    {
        $charger = new AppleCharger;
        $this->power = $charger->charge();
    }
}
// 充电
$iphone = new iPhone;
$iphone->charge();

使用依赖注入之后,我来决定给 iPhone 用哪一款充电器:

class iPhone
{
    private $power;
    private $charger;

    // 依赖注入充电器,╮(╯▽╰)╭哎算了只要是充电器就行
    public function __construct(Charger $charger)
    {
        $this->charger = $charger;
    }

    // 充电
    public function charge()
    {
        $this->power = $this->charger->charge();
    }
}
interface Charger
{
    public function charge();
}
// Laravel 容器
use Illuminate\Container\Container;
$container = Container::getInstance();

// 给它一个原装充电器:
$container->bind(Charger::class, AppleCharger::class);

// 或者给它其它充电器
$container->bind(Charger::class, OtherCharger::class);

// 充电
$iphone = $container->make(iPhone::class);
$iphone->charger();

可见,使用依赖注入之后,控制权「反转」了,由外部来决定给它什么充电器 (依赖对象)。 Laravel 管这个 容器控制程序Service Container (服务容器),它来控制着各种依赖的获取方法。

更多关于 Laravel 依赖注入、服务容器的知识可以参考以前的文章。

扩展知识

依赖注入实现方式:

  • 基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。
  • 基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
  • 基于 set 方法。实现特定属性的 public set 方法,来让外部容器调用传入所依赖类型的对象。
  • 基于注解。基于 Java 的注解功能,在私有变量前加 "@Autowired" 等注解,不需要显式的定义以上三种代码,便可以让外部容器传入对应的对象。该方案相当于定义了 public 的 set 方法,但是因为没有真正的 set 方法,从而不会为了实现依赖注入导致暴露了不该暴露的接口(因为 set 方法只想让容器访问来注入而并不希望其他依赖此类的对象访问)。

依赖查找:

依赖查找更加主动,在需要的时候通过调用框架提供的方法来获取对象,获取时需要提供相关的配置文件路径、key等信息来确定获取对象的状态。

You can’t perform that action at this time.