php - Laravel4 IOC容器的好处

标签 php laravel-4 ioc-container loose-coupling

我很难理解 IOC 容器在依赖注入(inject)范围内的好处。
考虑这个基本示例:

App::bind('Car', function()
{
    return new Car;
});

Route::get('/', function()
{
    dd(App::make('Car'));  //  resolve it
}); 

我没有看到使用 IOC 容器比在构造函数中创建新实例有什么好处。
除了测试的好处,我读到原因是松耦合。
但是,由于“汽车”绑定(bind)仅返回新车的一个实例,因此我看不出这个示例在哪种意义上会更加松散耦合。
对我来说,两者似乎在做完全相同的事情。

最佳答案

你是对的,在人为的例子中,通常很难准确地看出你得到了什么好处。考虑一个更接近真实世界的示例 Controller :

class TestController
{
    public function __construct(CarRepositoryInterface $car)
    {
        $this->_repository = $car;
    }

    public function route($id)
    {
        return View::make('my.view')->with('car', $this->_repository->find($id));
    }
}

非常简单,一个存储库被注入(inject)到 Controller 的构造函数中,然后在 route 使用它通过 id 加载特定的汽车。这里存储库的细节并不是那么重要,大概有一个服务提供商将 CarRepositoryInterface 绑定(bind)到具体的 CarRepository 实现:

class RepositoryServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('CarRepositoryInterface', function($app) {
            return new EloquentCarRepository(new Car());
        });
    }
}

就是这样,每次构造 Controller 时,都会创建一个 EloquentCarRepository 并将其注入(inject)到构造函数中供 Controller 使用。

但是等等,如果您想从使用 Eloquent 切换到说 Doctrine 会怎样?由于我们在这里利用依赖注入(inject),您不必更改 Controller 中的一行代码(或可能正在使用您当前实现的任何其他 Controller )。您所要做的就是定义 CarRepositoryInterface 的其他实现,例如 DoctrineCarRepository,并在您的服务提供商中更改一行代码:

return new DoctrineCarRepository();

依赖于 CarRepositoryInterface 的所有其他内容现在神奇地有效。而这一切都要归功于国际奥委会。

您还可以向您的服务提供商添加更复杂的逻辑:

public function register()
{
    $this->app->bind('CarRepositoryInterface', function($app) {
        if($app->environment() == 'production') {
            return new EloquentCarRepository(new Car());
        } else {
            return new DoctrineCarRepository(new Car());
        }
    });
}

此处 EloquentCarRepository 将仅在生产环境中使用,而在任何其他环境中将使用 DoctrineCarRepository。 (这个例子只是为了展示你如何能够更好地控制在运行时构建什么类型的对象,而不是我提倡实际这样做......)

附录

正如我在评论中所述,这是一种使用类型,您在运行时之前不太确定需要什么类型的对象。还有一个用法:依赖管理。

假设您有一个对象依赖于另一个对象:

class MyObject
{
    public function __construct(AnotherObject $obj)
    {
        $this->obj = $obj;
    }
}

还假设 AnotherObject 依赖于另一个对象:

class AnotherObject
{
    public function __construct(YetAnotherObject $obj)
    {
        $this->obj = $obj;
    }
}

这可能会很快失控,最终会产生一长串需要满足的依赖关系,然后才能真正创建对象。使用 IoC,您只需从容器中取出一个实例:

$myObject = app()->make('MyObject');

只要 IoC 可以构建所有的依赖关系,你就不必做这样的事情:

$yetAnotherObj = new YetAnotherObject();
$anotherObj = new AnotherObject($yetAnotherObj);
$myObject = new MyObject($anotherObj);

关于php - Laravel4 IOC容器的好处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25251823/

相关文章:

unity-container - 如何使用统一根据注入(inject)的类型有条件地绑定(bind)实例?

php - 将 PHP 表添加到 mySQL 文件

php - 从另一台服务器远程连接到数据库

php - laravel 使用 Request::create 和 Route::dispatch($request);

php - 如何在 LARAVEL 4 上使用 TCPDF

.net - 与 asp.net mvc 一起使用的良好 IOC 框架?

ninject - Simpleinjctor 根据泛型类型获取实例

php - Sum table1 $date1 和 $date2 之间 AND 用户名等于 $user

php - 3 个表 mySQL 连接,具有来自同一列的 2 个 WHERE 子句 - 只有一个有效

php - Eloquent 查询构建器替换 and