依赖注入
依赖注入是个花俏的名词,事实上是指:类的依赖通过构造器或在某些情况下通过「setter」方法「注入」。先看一段 Laravel 控制器里的代码实例:
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Users\Repository as UserRepository;
class UserController extends Controller
{
/**
* 用户 Repository 的实例。
*/
protected $users;
/**
* 创建一个新的控制器实例。
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
/**
* 显示指定 ID 的用户。
*
* @param int $id
* @return View
*/
public function show($id)
{
$user_info = $this->users->find($id);
return view('user', ['user_info' => $user_info]);
}
}
Laravel 通过服务容器来管理类依赖并进行依赖注入。如果使用一个接口作为函数参数的类型提示,这个时候就需要将指定的实现绑定到接口上面:
interface EventPusher {
public function send($data);
}
class RedisEventPusher implements EventPusher {
public function send($data) {
//
}
}
$this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
use App\Contracts\EventPusher;
/**
* 创建一个新的类实例。
*
* @param EventPusher $pusher
* @return void
*/
public function __construct(EventPusher $pusher)
{
$this->pusher = $pusher;
}
这个就是所谓的面向接口编程,接口可以理解为一个规范、一个约束。高层模块不直接依赖于低层模块,它们都应该依赖于抽象(指接口)。
使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
控制反转
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则。其中**最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
<?php
/**
* 没有IoC/DI的时候,常规的A类使用C类的示例
*/
/**
* Class c
*/
class c
{
public function say()
{
echo 'hello';
}
}
/**
* Class a
*/
class a
{
private $c;
public function __construct()
{
$this->c = new C(); // 实例化创建C类
}
public function sayC()
{
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
*/
class c
{
public function say()
{
echo 'hello';
}
}
/**
* Class a
*/
class a
{
private $c;
public function setC(C $c)
{
$this->c = $c; // 实例化创建C类
}
public function sayC()
{
echo $this->c->say(); // 调用C类中的方法
}
}
$c = new C();
$a = new a();
$a->setC($c);
$a->sayC();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。