为什么实现了接口的类需要在 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的意义究竟是什么?

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
leo
最佳答案

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

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

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

6年前 评论
leo

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

6年前 评论

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

6年前 评论

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

5年前 评论

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

5年前 评论

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

5年前 评论

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

5年前 评论

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

4年前 评论

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

2年前 评论

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