为什么实现了接口的类需要在 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 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
leo
最佳答案

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

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

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

6年前 评论
leo

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

5年前 评论

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

5年前 评论

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

4年前 评论

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

2年前 评论

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