从百草园到三味书屋 (一)依赖注入

何为依赖注入?

简单分析如下代码,是否存在问题?
class UserController extends BaseController{     
    public function getIndex()     {         
        $users = User::all();         
        return View::make('users.index', compact('users'));     
    } 
}

分析:

  1. 这段代码很 简短,但我们要想测试这段代码的话就一定会和实际的数据库发生联系。

  2. 也就是说, Eloquent ORM(译者注:Laravel的数据库对象模型库)和该控制器有着紧耦合。如果不使用Eloquent ORM,不连接到实际数据库,我们就没办法运行或者测试这段代码。这段代码同时也违背了“关注分离”这个软件设计原则。

  3. 简单讲:这个控制器知道的太多了。 控制器不需要去了解数据是从哪儿来的,只要知道如何访问就行。控制器也不需要知道这数据是从MySQL或哪儿来的,只需要知道这数据目前是可用的。

Separation Of Concerns 关注分离

每一个类都应该有单独的职责,并且该职责应完全被这个类封装。

Build A Contract 建立约定

//定义接口
interface UserRepositoryInterface
{
    public function all();
}

//实现接口
class DbUserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all()->toArray();
    }
}

// 面向接口编程,通过构造函数,注入实例(实现接口的任意类实例)
class UserController extends BaseController
{
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }

    public function getIndex()
    {
        $users=$this->users->all();
        return View::make('users.index', compact('users'));
    }
}

分析:

  1. 现在我们的控制器就完全和数据层面无关了。在这里无知是福!

  2. 我们的数据可能来自MySQL,MongoDB或者Redis。我们的控制器不知道也不需要知道他们的区别。

  3. 仅仅做出了这么小小的改变,我们就可以独立于数据层来测试Web层了,将来切换存储实现也会很容易。

Respect Boundaries 严守边界

记得要保持清晰的责任边界。 控制器和路由是作为HTTP和你的应用程序之间的中间件来用的。当编写大型应用程序时,不要将你的领域逻辑混杂在其中(控制器、路由)。

示例:

场景:提醒用户交钱,需用到支付 和 通知 两个方法。

//定义账单支付接口
interface BillerInterface {
    public function bill(array $user, $amount);
}

//定义账单通知接口
interface BillingNotifierInterface {
    public function notify(array $user, $amount);
}

//实现账单支付接口,同时注入,账单通知接口
class StripeBiller implements BillerInterface{
    public function __construct(BillingNotifierInterface $notifier)
    {
        $this->notifier = $notifier;
    }

    public function bill(array $user, $amount)
    {
        $this->notifier->notify($user, $amount);
    }
}

//使用sms作为账单支付通知,那我们如何做依赖注入呢?很简单:
$biller = new StripeBiller(new SmsNotifier);

分析:

  1. 这就是依赖注入。(与容器ioc可以是脱离独立存在的,后面会讲解ioc)

  2. biller不需再考虑提醒用户的事儿,我们直接传给他一个提示器(notifier)。 这种微小的改动能使你的应用焕然一新。

  3. 你的代码马上就变得更容易维护, 因为明确指定了类的职责边界。 并且更容易测试, 你只需使用模拟依赖即可。

依赖注入核心

依赖注入的核心,是基于接口编程,实际目的在于解耦,使得类之间更加独立,健壮,易于维护。

原文链接: https://my.oschina.net/zgldh?tab=newest&am...

本作品采用《CC 协议》,转载必须注明作者和本文链接
写的不好,就当是整理下思绪吧。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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