首页 > 解决方案 > 为什么 laravel 主要使用 Facades 而不是单例?

问题描述

在这里阅读时,您会发现外墙并不是真正的外墙

为什么 laravel 的门面表现得像一个单例?

无论如何,Facades 上的所有方法都是静态的(去看看你自己Illuminate\Support\Facades

有些别名实际上就是这样,例如普通类

'Arr' => Illuminate\Support\Arr::class,

它是外墙有什么意义?

标签: laravellaravel-8

解决方案


为什么 laravel 主要使用 Facades 而不是单例?

Facades 是单例的,因为它们的实现方式。

首先,让我们定义一些我们正在使用的术语:

Facade可以参考两件事:

  1. Laravel 的 Facades,一种用于方便开发人员的工具,也是依赖注入的替代方案
  2. 面设计模式。Laravel 的 Facades不是外观设计模式的实现。对于那些刚接触 Laravel 但熟悉外观设计模式的人来说,这是一个常见的困惑点。Laravel 的 Facades 最好被认为是Laravel 容器中服务的静态代理。

Singleton是一种创建型设计模式,可让您确保一个类只有一个实例,同时提供对该实例的全局访问点。(来源

这些定义并不相互排斥。某些东西可以是外观单例(它们是否应该是不同的对话)。

Laravel 的 Facade 有两种方式是单例:抽象 Facade 类和 Laravel 的 IoC Container。

抽象Facade——所有单个 Facade的父级——是 Facade 充当单例的主要原因。当调用 Facade 时,它​​会从 Laravel 的容器中解析其底层类并将其保存到本地静态属性中。后续调用将引用本地属性值,而不是再次从容器中解析。

Laravel 的 Inversion of Control Container是 Facade 可以引用单例对象的另一种方式。当您将服务绑定到容器时,您可以使用它Container::singleton()来确保服务在检索时始终解析为相同的实例。

我希望澄清一些东西可以同时是单例外观。

有些别名实际上就是这样,例如普通类

在这种情况下,别名只是对 PHP 的调用class_alias(),是一种通过最小化完全限定的类名(命名空间 + 类名)来使 Facades 和其他类更易于使用的方法。而不是需要use Illuminate\Support\Arr;,您可以只use Arr;\Arr::get()在您的代码中不导入。这在 Blade 模板中特别有用。这些别名可用于但不限于 Facades。

如果所有函数都是静态的,为什么所有的辅助函数session()都使用->例如config()->set()vs config()::set() when the facade doesConfig::set()`?

只是目的和实施的不同。Facade 是一个代理——所有交互都发生在 Facade 本身,但它代理对底层服务的请求。辅助函数不代理任何调用,它们只返回从容器中检索到的服务。

// Only interacts with the Facade class.
// set() is proxied via the magic __callStatic() method.
Config::set();

// config() returns an instance of the Config Repository class.
// Subsequent calls are directly on that instance.
// No magic methods used.
config()->set();

Facades 还带有一些模拟和测试实用程序,这可能会使它们成为更好的解决方案,具体取决于您的测试需求。


推荐阅读