Laravel 4:Facade 与 DI(何时使用)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19193532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 4: Facade vs DI (when to use)
提问by kablamus
My understanding is that a facade is used as an alternative to dependency injection. Please correct if I'm mistaken. What is not clear is when one should use one or the other.
我的理解是使用外观作为依赖注入的替代方案。如果我错了,请纠正。不清楚的是什么时候应该使用一种或另一种。
What are the advantages/disadvantages of each approach? How should I determine when to use one or the other?
每种方法的优点/缺点是什么?我应该如何确定何时使用其中之一?
Lastly, why not use both? I can create a facade that references an interface. It seems Sentry 2 is written this way. Is there a best practice?
最后,为什么不同时使用两者?我可以创建一个引用接口的外观。Sentry 2 似乎是这样写的。有最佳实践吗?
回答by Antonio Carlos Ribeiro
FACADES
立面
Facadesare not an alternative to dependency injection.
Facades 不能替代依赖注入。
Laravel Facade is an implementation of the Service Locator Pattern, creating a clean and beautiful way of accessing objects:
Laravel Facade 是 Service Locator Pattern 的一个实现,它创建了一种干净漂亮的访问对象的方式:
MyClass::doSomething();
This is the PHP syntax for a static methods, but Laravel changes the game and make them non-static behind the scenes, giving you a beautiful, enjoyable and testable way of writing your applications.
这是静态方法的 PHP 语法,但 Laravel 改变了游戏规则,使它们在幕后成为非静态的,为您提供了一种漂亮、愉快和可测试的编写应用程序的方式。
DEPENDENCY INJECTION
依赖注入
Dependency Injection is, basically, a way of passing parameters to your constructors and methods while automatically instatiating them.
基本上,依赖注入是一种将参数传递给构造函数和方法同时自动实例化它们的方法。
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
}
}
A better construction of it would be using Interfaces on your Dependency Injected constructors:
更好的构造方法是在依赖注入的构造函数上使用接口:
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
}
}
But note that in Laravel you can inject classes and interfaces the same way. To inject interfaces you just have to tell it wich one will be this way:
但请注意,在 Laravel 中,您可以以相同的方式注入类和接口。要注入接口,你只需要告诉它哪个将是这样的:
App::bind('MyInterface', 'MyOtherClass');
This will tell Laravel that every time one of your methods needs an instance of MyInterface it should give it one of MyOtherClass.
这将告诉 Laravel,每次你的方法之一需要一个 MyInterface 的实例时,它应该给它一个 MyOtherClass。
What happens here is that this constuctor has a "dependency": MyOtherClass
, which will be automatically injected by Laravel using the IoC container. So, when you create an instance of MyClass
, Laravel automatically will create an instance of MyOtherClass
and put it in the variable $class
.
这里发生的事情是这个构造函数有一个“依赖项”:MyOtherClass
,它将被 Laravel 使用IoC 容器自动注入。因此,当您创建 的实例时MyClass
,Laravel 会自动创建一个 的实例MyOtherClass
并将其放入变量中$class
。
Dependency Injection is just an odd jargon developers created to do something as simple as "automatic generation of parameters".
依赖注入只是开发人员创建的一个奇怪的行话,用来做一些像“自动生成参数”这样简单的事情。
WHEN TO USE ONE OR THE OTHER?
何时使用其中之一?
As you can see, they are completely different things, so you won't ever need to decide between them, but you will have to decide where go to with one or the other in different parts of your application.
正如您所看到的,它们是完全不同的东西,因此您永远不需要在它们之间做出决定,但是您必须决定在应用程序的不同部分使用一个或另一个的位置。
Use Facadesto ease the way you write your code. For example: it's a good practice to create packages for your application modules, so, to create Facades for those packages is also a way to make them seem like a Laravel public class and accessing them using the static syntax.
使用 Facades简化您编写代码的方式。例如:为应用程序模块创建包是一个很好的做法,因此,为这些包创建 Facades 也是一种使它们看起来像 Laravel 公共类并使用静态语法访问它们的方法。
Use Dependency Injectionevery time your class needs to use data or processing from another class. It will make your code testable, because you will be able to "inject" a mock of those dependencies into your class and you will be also exercising the single responsibilityprinciple (take a look at the SOLID principles).
每次您的类需要使用来自另一个类的数据或处理时,请使用依赖注入。它将使您的代码可测试,因为您将能够将这些依赖项的模拟“注入”到您的类中,并且您还将行使单一职责原则(查看SOLID 原则)。
回答by fideloper
Facades, as noted, are intended to simplify a potentially complicated interface.
如前所述,外观旨在简化潜在复杂的界面。
Facades are still testable
外墙仍然可以测试
Laravel's implementation goes a step further and allows you to define the base-class that the Facade "points" to.
Laravel 的实现更进一步,允许您定义 Facade“指向”的基类。
This gives a developer the ability to "mock" a Facade - by switching the base-class out with a mock object.
这使开发人员能够“模拟” Facade - 通过使用模拟对象切换基类。
In that sense, you can use them and still have testable code. This is where some confusion lies within the PHP community.
从这个意义上说,您可以使用它们并且仍然拥有可测试的代码。这就是 PHP 社区中存在一些混乱的地方。
DI is often cited as making your code testable - they make mocking class dependencies easy. (Sidenote: Interfaces and DI have other important reasons for existing!)
DI 通常被引用为使您的代码可测试 - 它们使模拟类依赖关系变得容易。(旁注:接口和 DI 存在还有其他重要原因!)
Facades, on the other hand, are often cited as making testing harder because you can't "simply inject a mock object" into whatever code you're testing. However, as noted, you can in fact "mock" them.
另一方面,Facades 通常被认为会使测试变得更加困难,因为您不能“简单地将模拟对象”注入您正在测试的任何代码中。但是,如前所述,您实际上可以“模拟”它们。
Facade vs DI
外观与 DI
This is where people get confused regarding whether Facades are an alternative to DI or not.
这就是人们对 Facades 是否可以替代 DI 感到困惑的地方。
In a sense, they both add a dependency to your class - You can either use DI to add a dependency or you can use a Facade directly - FacadeName::method($param);
. (Hopefully you are not instantiating any class directly within another :D ).
从某种意义上说,它们都为您的类添加了依赖项 - 您可以使用 DI 添加依赖项,也可以直接使用 Facade - FacadeName::method($param);
。(希望您没有直接在另一个 :D 中实例化任何类)。
This does not make Facades an alternative to DI, but instead, within Laravel, does create a situation where you may decide to add class dependencies one of 2 ways - either using DI or by using a Facade. (You can, of course, use other ways. These "2 ways" are just the most-often used "testable way").
这并没有使 Facades 成为 DI 的替代品,而是在 Laravel 中创建了一种情况,您可以决定通过两种方式之一添加类依赖项 - 使用 DI 或使用 Facade。(当然,您可以使用其他方式。这些“2 种方式”只是最常用的“可测试方式”)。
回答by Shawn McCool
Laravel's Facades are an implementation of the Service Locator pattern, not the Facade pattern.
Laravel 的 Facades 是 Service Locator 模式的实现,而不是 Facade 模式。
In my opinion you should avoid service locator within your domain, opting to only use it in your service and web transport layers.
在我看来,您应该避免在您的域中使用服务定位器,选择仅在您的服务和 Web 传输层中使用它。
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
回答by Paris Paraskeva
I think that in terms of laravel Facades help you keep you code simple and still testable since you can mock facades however might be a bit harder to tell a controllers dependencies if you use facades since they are probably all over the place in your code.
我认为就 Laravel Facades 而言,可以帮助您保持代码简单且仍然可测试,因为您可以模拟 Facades,但是如果您使用 Facades,那么告诉控制器依赖项可能会有点困难,因为它们可能在您的代码中无处不在。
With dependency injection you need to write a bit more code since you need to deal with creating interfaces and services to handle the depenancies however Its a lot more clear later on what a controller depends on since these are clearly mentioned in the controller constructor.
使用依赖注入,您需要编写更多代码,因为您需要处理创建接口和服务来处理依赖关系,但是稍后会更清楚控制器依赖什么,因为这些在控制器构造函数中明确提及。
I guess it's a matter of deciding which method you prefer using
我想这是决定您更喜欢使用哪种方法的问题