php依赖注入 简书,php之依赖注入和控制反转

本文详细介绍了依赖注入(Dependency Injection, DI)和控制反转(Inversion of Control, IOC)的概念,通过实例展示了如何通过构造器注入和工厂模式实现DI。进一步地,引入了IoC容器的概念,利用Registry注册和解决依赖,以提高代码的解耦性和可维护性。文章强调了依赖注入在减少代码耦合和简化维护方面的重要性。
摘要由CSDN通过智能技术生成

以前一直对依赖注入和控制反转理解不清,或理解不深,这里总结一番!

1. 什么是依赖注入?

IOC:英文全称:Inversion of Control,简称IOC,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection,简称DI)。

当一个类的实例需要另一个类的实例协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。而采用依赖注入的方式,创建被调用者的工作不再由调用者来完成,因此叫控制反转,创建被调用者的实例的工作由IOC容器来完成,然后注入调用者,因此也称为依赖注入。

下面通过例子解析:

class A

{

public $b;

public $c;

public function A()

{

//TODO

}

public function Method()

{

$this->b=new B();

$this->c=new C();

$this->b->Method();

$this->c->Method();

//TODO

}

}

class B

{

public function B()

{

//TODO

}

public function Method()

{

//TODO

echo 'b';

}

}

class C

{

public function C()

{

//TODO

}

public function Method()

{

//TODO

echo 'c';

}

}

$a=new A();

$a->Method();

?>

上面代码,我们很容易理解一句话:A类依赖B类和C类

也就是说,如果今后开发过程中,要对B类或者C类修改,一旦涉及函数改名,函数参数数量变动,甚至整个类结构的调整,我们也要对A类做出相应的调整,A类的独立性丧失了,这在开发过程中是很不方便的,也就是我们说的“牵一发动全身”,如果两个类是两个人分别写的,矛盾往往就在这个时候产生了。。。

万一真的要改动B类和C类,有没有办法,可以不去改动或者尽量少改动A类的代码呢?这里要用到控制反转。

控制反转(IOC)是一种思想,依赖注入(DI)是实施这种思想的方法。

第一种方法叫做:构造器注入(这种方法也不推荐用,但比不用要好)

class A

{

public $b;

public $c;

public function A($b,$c)

{

$this->b=$b;

$this->c=$c;

}

public function Method()

{

$this->b->Method();

$this->c->Method();

}

}

$a=new A(new B(),new C());

$a->Method();

A类的构造器依赖B类和C类,通过构造器的参数传入,至少实现了一点,就是B类对象b和C类对象c的创建都移至了A类外,所以一旦B类和C类发生改动,A类无需做修改,只要在client类里改就可以了

第二种方法叫做:工厂模式注入(可以使用)

新添加一个工厂

class Factory

{

public function Factory()

{

//TODO

}

public function create($s)

{

switch($s)

{

case 'B':

{

return new B();

break;

}

case 'C':

{

return new C();

break;

}

default:

{

return null;

break;

}

}

}

}

改动A类为:

class A

{

public $b;

public $c;

public function A()

{

//TODO

}

public function Method()

{

$f=new Factory();

$this->b=$f->create('B');

$this->c=$f->create('C');

$this->b->Method();

$this->c->Method();

//TODO

}

}

这是一个使用工厂模块的依赖注入和控制反转具体实例。A类不再直接生成B类,C类,而交给工厂控制生成(这是一个控制反转),生成实例后注入到A类的变量中,这里实现了依赖注入。

使用工厂模式虽然很多程度解耦了代码,但是除了B,C还有更多D,E,F等等的时候呢,这时候,我们可以使用registry注册。

class Ioc {

/**

* @var 注册的依赖数组

*/

protected static $registry = array();

/**

* 添加一个resolve到registry数组中

* @param string $name 依赖标识

* @param object $resolve 一个匿名函数用来创建实例

* @return void

*/

public static function register($name, Closure $resolve)

{

static::$registry[$name] = $resolve;

}

/**

* 返回一个实例

* @param string $name 依赖的标识

* @return mixed

*/

public static function resolve($name)

{

if ( static::registered($name) )

{

$name = static::$registry[$name];

return $name();

}

throw new Exception('Nothing registered with that name, fool.');

}

/**

* 查询某个依赖实例是否存在

* @param string $name id

* @return bool

*/

public static function registered($name)

{

return array_key_exists($name, static::$registry);

}

}

现在就可以通过如下方式来注册和注入一个

$book = Ioc::registry('book', function(){

$book = new Book;

$book->setdb('...');

$book->setprice('...');

return $book;

});

//注入依赖

$book = Ioc::resolve('book');

?>

这样我们需要用到那个类,就直接使用DI注册一个

这里相当于抽象了一个万能工厂,这个工厂什么都可以做,但是没有材料,需要你提供加工材料 ,他只负责加工,并且保存,下次需要直接过来拿,不需要重新加工;而上面的工厂模式,这个工厂已经提供了材料,但是提供的材料有限,他只能在这些已经存在的材料中加工,区别就在这里。

参考文章有:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值