Laravel 4:Facade vs DI(何时使用)

kab*_*mus 16 dependency-injection laravel laravel-4

我的理解是外立面被用作依赖注入的替代方案.如果我弄错了,请纠正.不清楚的是何时应该使用其中一种.

每种方法的优点/缺点是什么?我该如何确定何时使用其中一种?

最后,为什么不同时使用?我可以创建一个引用界面的外观.哨兵2似乎是这样写的.有最好的做法吗?

Ant*_*iro 34

FACADES

外墙不是依赖注入的替代方案.

Laravel Facade是Service Locator Pattern的一个实现,创建了一种干净漂亮的访问对象的方式:

MyClass::doSomething();
Run Code Online (Sandbox Code Playgroud)

这是静态方法的PHP语法,但Laravel更改了游戏并使其在幕后非静态,为您提供了一种美观,愉快且可测试的编写应用程序的方法.

依赖性注射

基本上,依赖注入是一种将参数传递给构造函数和方法的方法,同时自动对它们进行实例化.

class MyClass {

    private $property;

    public function __construct(MyOtherClass $property)
    {
        /// Here you can use the magic of Dependency Injection

        $this->property = $property

        /// $property already is an object of MyOtherClass
    }

}
Run Code Online (Sandbox Code Playgroud)

更好的构造是在Dependency Injected构造函数上使用Interfaces:

class MyClass {

    private $property;

    public function __construct(MyInterface $property)
    {
        /// Here you can use the magic of Dependency Injection

        $this->property = $property

        /// $property will receive an object of a concrete class that implements MyInterface
        /// This class should be defined in Laravel elsewhere, but this is a way of also make 
        /// your application easy to maintain, because you can swap implementations of your interfaces
        /// easily
    }

}
Run Code Online (Sandbox Code Playgroud)

但请注意,在Laravel中,您可以以相同的方式注入类和接口.要注入接口,你只需告诉它一个人就是这样:

App::bind('MyInterface', 'MyOtherClass');
Run Code Online (Sandbox Code Playgroud)

这将告诉Laravel每当你的一个方法需要一个MyInterface实例时,它应该给它一个MyOtherClass.

这里发生的是这个构造函数有一个"依赖":MyOtherClass它将由Laravel使用IoC容器自动注入.因此,当您创建一个实例时MyClass,Laravel会自动创建一个实例MyOtherClass并将其放入变量中$class.

依赖注入只是一个奇怪的行话,开发人员创建的东西就像"自动生成参数"一样简单.

何时使用其中一个或另一个?

正如您所看到的,它们是完全不同的东西,因此您不需要在它们之间做出决定,但是您必须决定在应用程序的不同部分中使用哪一个.

使用Facades可以简化编写代码的方式.例如:为您的应用程序模块创建包是一个很好的做法,因此,为这些包创建Facade也是一种使它们看起来像Laravel公共类并使用静态语法访问它们的方法.

每当您的类需要使用其他类的数据或处理时,请使用依赖注入.它将使您的代码可测试,因为您将能够将这些依赖项的模拟"注入"到您的类中,并且您还将执行单一责任原则(请参阅SOLID原则).

  • 我无法真正发现差异.与依赖注入一样,您可以构建Facade模拟,因此您的代码仍然可以测试,并且仍然使用IoC容器解析依赖项.实际上,它们只是IoC容器的"静态"访问器.我看到的唯一区别是,通过使用依赖注入,您可以依赖于接口,而使用Facades,您依赖于类.你能澄清一下吗? (2认同)

fid*_*per 11

如上所述,外墙旨在简化可能复杂的界面.

外墙仍然可以测试

Laravel的实现更进一步,允许您定义Facade"指向"的基类.

这使开发人员能够"模拟"Facade - 通过使用模拟对象切换基类.

从这个意义上讲,您可以使用它们并且仍然具有可测试的代码.这是PHP社区中存在一些混乱的地方.

DI通常被认为是使您的代码可测试 - 它们使得模拟类依赖性变得容易.(旁注:接口和DI还有其他重要原因!)

另一方面,外墙通常被认为更难以进行测试,因为您不能"简单地将模拟对象注入"您正在测试的任何代码中.但是,如上所述,您实际上可以"嘲笑"它们.

门面vs DI

这是人们对Facade是否是DI的替代品感到困惑的地方.

从某种意义上说,它们都为您的类添加了一个依赖项 - 您可以使用DI来添加依赖项,也可以直接使用Facade FacadeName::method($param);.(希望你没有直接在另一个类中实例化任何类:D).

这并不能使Facade成为DI的替代品,而是在Laravel中创建一种情况,您可以决定以两种方式之一添加类依赖关系 - 使用DI或使用Facade.(当然,您可以使用其他方式.这些"两种方式"只是最常用的"可测试方式").