我的理解是外立面被用作依赖注入的替代方案。如果我弄错了,请纠正。不清楚的是何时应该使用其中一种。
每种方法的优点/缺点是什么?我该如何确定何时使用其中一种?
最后,为什么不同时使用?我可以创建一个引用界面的外观。哨兵2似乎是这样写的。有最好的做法吗?
答案 0 :(得分:34)
<强> FACADES 强>
Facades不是依赖注入的替代方法。
Laravel Facade是服务定位器模式的一个实现,创建了一种干净漂亮的访问对象的方式:
MyClass::doSomething();
这是静态方法的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
}
}
更好的构造方法是在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
}
}
但请注意,在Laravel中,您可以以相同的方式注入类和接口。要注入接口,你只需告诉它将是这样的:
App::bind('MyInterface', 'MyOtherClass');
这将告诉Laravel每当你的一个方法需要一个MyInterface实例时,它应该给它一个MyOtherClass。
这里发生的是这个构造函数有一个“依赖”:MyOtherClass
,它将由Laravel使用IoC container自动注入。因此,当您创建MyClass
的实例时,Laravel会自动创建MyOtherClass
的实例并将其放入变量$class
。
依赖注入只是一个奇怪的术语开发人员,他们创建了一些像“自动生成参数”这样简单的东西。
何时使用其他人?
正如您所看到的,它们是完全不同的东西,因此您不需要在它们之间做出决定,但您必须决定在应用程序的不同部分中使用哪一个。
使用Facades 可简化您编写代码的方式。例如:为您的应用程序模块创建包是一个很好的做法,因此,为这些包创建Facade也是一种使它们看起来像Laravel公共类并使用静态语法访问它们的方法。
每当您的类需要使用其他类的数据或处理时,使用依赖注入。它将使您的代码可测试,因为您将能够将这些依赖项的模拟“注入”到您的类中,并且您还将执行single responsibility原则(请查看SOLID principles)。
答案 1 :(得分:11)
如上所述,Facades旨在简化可能复杂的界面。
Laravel的实现更进一步,允许您定义Facade“指向”的基类。
这使开发人员能够“模拟”Facade - 通过模拟对象切换基类。
从这个意义上说,你可以使用它们并且仍然有可测试的代码。这是PHP社区中的一些混乱。
DI通常被认为是使您的代码可测试 - 它们使得模拟类依赖性变得容易。 (旁注:接口和DI有其他重要原因存在!)
另一方面,Facades通常被认为是更难以测试,因为你不能“简单地将模拟对象注入”你正在测试的任何代码中。但是,如上所述,您实际上可以“嘲笑”它们。这是人们对Facade是否是DI的替代品感到困惑的地方。
从某种意义上说,它们都会为您的类添加依赖关系 - 您可以使用DI添加依赖关系,也可以直接使用Facade - FacadeName::method($param);
。 (希望你没有直接在另一个类中实例化任何类:D)。
这不会使Facade成为DI的替代品,而是在Laravel中,确实会创建一种情况,您可以决定以两种方式之一添加类依赖关系 - 使用DI或使用Facade。 (当然,您可以使用其他方式。这些“两种方式”只是最常用的“可测试方式”)。
答案 2 :(得分:1)
Laravel的Facades是服务定位器模式的实现,而不是Facade模式。
在我看来,您应该避开域中的服务定位器,只选择在服务和Web传输层中使用它。
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
答案 3 :(得分:0)
我认为就laravel而言,Facade可以帮助你保持代码简单并且仍然可以测试,因为你可以模拟外观但是如果你使用外墙可能有点难以告诉控制器依赖,因为它们可能在你的地方到处都是代码。
使用依赖注入,你需要编写更多的代码,因为你需要处理创建接口和服务来处理依赖项,但是后来在控制器所依赖的内容上要清楚得多,因为这些在控制器构造函数中有明确提及
我想这是决定使用哪种方法
的问题