为什么实现了接口的类需要在 provider 里绑定,直接在使用的地方注入不也一样吗?

{tip} 如果某个容器不依赖于任何接口就没必要去绑定类在这个容器里。
文档里有这么一句话吸引了我的注意。就拿文档后面的例子来举例:

$this->app->bind(
'App\Contracts\EventPusher',
'App\Services\RedisEventPusher'
);

这样绑定一下的意义何在?
它的效果是:

public function __construct(EventPusher $pusher)
{
$this->pusher = $pusher;
}

这样注入EventPusher的时候(其实它是个接口),却实际注入了一个具体实现了的RedisEventPusher。
可我就是无法理解这样做的意义——既然绑定了RedisEventPusher到EventPusher上,让程序默认使用RedisEventPusher,那就说明,我只想用RedisEventPusher了,不会再有DbEventPusher、RabbitMQEventPusher等等实现了吧?那为啥还要绑定?为什么我不直接:

public function __construct(RedisEventPusher $pusher)
{
$this->pusher = $pusher;
}

当我想要用别的DbEventPusher的时候,我也可以:

public function __construct(DbEventPusher $pusher)
{
$this->pusher = $pusher;
}

这样不是很好吗?
所以,哪位大神来给我解惑一下,这个bind的意义究竟是什么?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
leo
最佳答案

假如有 100 个类都需要 EventPusher 作为构造函数的参数,然后你想把 Redis 改成 DB,想想这个工作量就爽歪歪。

5年前 评论
讨论数量: 8
leo

假如有 100 个类都需要 EventPusher 作为构造函数的参数,然后你想把 Redis 改成 DB,想想这个工作量就爽歪歪。

5年前 评论
leo

假如有 100 个类都需要 EventPusher 作为构造函数的参数,然后你想把 Redis 改成 DB,想想这个工作量就爽歪歪。

5年前 评论

@leo 卧槽,我怎么没想到呢,白打了这么多字

5年前 评论

@kiyoma 之前我也想过这个问题,服务容器其实就是做一个类的依赖管理。

5年前 评论

所以要依赖接口,不能依赖实现 :joy:

5年前 评论

面向接口编程!
当你使用 RedisEventPusher 类型提示的时候,就意味着你面向具体编程。这是不应该的。

4年前 评论

这个问题问的很棒,回答的也很👍

4年前 评论

我懂了,使用接口的写法是为了扩展性。虽然看上去好像多了一到手,但是为后续扩展留好了接口

3年前 评论

答得好,问得也好,不问这题一众小白恐怕连问都不知道如何问

1年前 评论

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