依赖注入
依赖注入是个花俏的名词,事实上是指:类的依赖通过构造器或在某些情况下通过「setter」方法「注入」。先看一段 Laravel 控制器里的代码实例:
<?php
namespaceApp\Http\Controllers;
useIlluminate\Routing\Controller;
useApp\Users\RepositoryasUserRepository;
classUserControllerextendsController
{
/**
* 用户Repository 的实例。
*/
protected$users;
/**
* 创建一个新的控制器实例。
*
* @param UserRepository $users
* @return void
*/
publicfunction__construct(UserRepository$users)
{
$this->users= $users;
}
/**
* 显示指定 ID 的用户。
*
* @param int $id
* @return View
*/
publicfunctionshow($id)
{
$user_info = $this->users->find($id);
returnview('user', ['user_info'=> $user_info]);
}
}
Laravel 通过服务容器来管理类依赖并进行依赖注入。如果使用一个接口作为函数参数的类型提示,这个时候就需要将指定的实现绑定到接口上面:
interfaceEventPusher {
publicfunctionsend($data);
}
classRedisEventPusherimplementsEventPusher {
publicfunctionsend($data) {
//
}
}
$this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
useApp\Contracts\EventPusher;
/**
* 创建一个新的类实例。
*
* @param EventPusher $pusher
* @return void
*/
publicfunction__construct(EventPusher$pusher)
{
$this->pusher= $pusher;
}
这个就是所谓的面向接口编程,接口可以理解为一个规范、一个约束。高层模块不直接依赖于低层模块,它们都应该依赖于抽象(指接口)。
使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
控制反转
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则。其中**最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(DependencyLookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
<?php
/**
* 没有IoC/DI的时候,常规的A类使用C类的示例
*/
/**
* Class c
*/
classc
{
publicfunctionsay()
{
echo'hello';
}
}
/**
* Class a
*/
classa
{
private$c;
publicfunction__construct()
{
$this->c= new C(); // 实例化创建C类
}
publicfunctionsayC()
{
echo$this->c->say();// 调用C类中的方法
}
}
$a = new a();
$a->sayC();
当有了IoC/DI的容器后,A类不再主动去创建C了,如下图所示:
而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中,如下图所示:
<?php
/**
* 当有了IoC/DI的容器后,a类依赖c实例注入的示例
*/
/**
* Class c
*/
classc
{
publicfunctionsay()
{
echo'hello';
}
}
/**
* Class a
*/
classa
{
private$c;
publicfunctionsetC(C $c)
{
$this->c= $c; // 实例化创建C类
}
publicfunctionsayC()
{
echo$this->c->say();// 调用C类中的方法
}
}
$c = new C();
$a = new a();
$a->setC($c);
$a->sayC();