将接口绑定到实现

注入具体依赖

服务容器有个非常强大特色,能够绑定特定实例的接口。举例,假设我们应用程序要集成 Pusher 服务去收发即时事件,如果使用 Pusher 的 PHP SDK,可以在类注入一个 Pusher 客户端实例:

<?php namespace AppHandlersCommands;

use AppCommandsCreateOrder;
use PusherClient as PusherClient;

class CreateOrderHandler {

    /**
     * Pusher SDK 客户端实例
     */
    protected $pusher;

    /**
     * 创建一个实例
     *
     * @param  PusherClient  $pusher
     * @return void
     */
    public function __construct(PusherClient $pusher)
    {
        $this->pusher = $pusher;
    }

    /**
     * 执行命令
     *
     * @param  CreateOrder  $command
     * @return void
     */
    public function execute(CreateOrder $command)
    {
        //
    }

}

在上面这个例子中,注入类的依赖到类中已经能够满足需求;但同时,我们也紧密耦合于 Pusher 的 SDK 。如果 Pusher 的 SDK 方法发生改变,或者我们要切换到别的事件服务,那我们也需要同时修改 CreateOrderHandler 的代码。

为接口编程

为了将 CreateOrderHandler 和事件推送的修改「隔离」,我们可以定义一个 EventPusher 接口和一个 PusherEventPusher 实现:

<?php namespace AppContracts;

interface EventPusher {

    /**
     * Push a new event to all clients.
     *
     * @param  string  $event
     * @param  array  $data
     * @return void
     */
    public function push($event, array $data);

}

一旦 PusherEventPusher 实现这接口,就可以在服务容器像这样注册它:

$this->app->bind("AppContractsEventPusher", "AppServicesPusherEventPusher");

当有类需要 EventPusher 接口时,会告诉容器应该注入 PusherEventPusher,现在就可以在构造器中「类型指定」一个 EventPusher 接口:

    /**
     * Create a new order handler instance.
     *
     * @param  EventPusher  $pusher
     * @return void
     */
    public function __construct(EventPusher $pusher)
    {
        $this->pusher = $pusher;
    }

文章导航