全局 vs 函数 vs 静态类方法


Global vs function vs static class method

假设你有一个唯一的对象,并且所有其他类和函数都在使用它......像$application.

您将如何在函数中访问此对象?

  1. 在每个函数中使用全局变量:

    global $application;
    $application->doStuff();
    
  2. 创建一个函数,如application(),将对象实例化为静态变量并返回它;然后在需要访问该对象的任何位置使用此函数:

    application()->doStuff();
    
  3. 创建一个单例事物,例如返回唯一实例的对象类中的静态方法,并使用此方法访问该对象:

    Application::getInstance()->doStuff();
    
  4. KingCrunch & skwee:将应用程序对象作为参数传递给需要的每个函数/类

    ...
    public function __construct(Application $app, ...){
      ....
    

如果有其他选项,请发布它们。我想知道这些选项中哪一个是最有效/被认为是"最佳实践"的。

我会把它传递给所有需要的方法。即

function doFoo(Application $app) {
    $app->doStuff();
}

全局和单例都被认为是不好的,并且过多地束缚了您的代码,这使得单元测试更加困难。当您对以下语句回答"是"时,有一条规则允许您使用单例:

是否需要向我的应用程序引入全局状态,并且我必须具有给定对象的单个实例,并且具有多个实例将导致错误

如果您对所有 3 个部分的回答都是肯定的,那么您可以使用单例。在任何其他情况下,只需将所有实例传递给需要它们的所有方法即可。如果你有太多的上下文,请考虑使用类似上下文的东西

class Context {
    public $application;
    public $logger;
    ....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
    $context->application->doStuff();
    $context->logger->logThings();
}

(如果您需要保护数据或操作数据,或者如果您想使用惰性启动等,则可以使用 getter/setter(。

祝你好运!

单例、上帝类、单体类等都是反模式,所以我建议第四种选择:依赖注入。 您可以通过工厂在应用程序中创建application实例(如果它没有依赖项,甚至可以new,但这最终会使事情复杂化(。

然后,任何需要访问application的类都可以通过构造函数将其作为成员获取。 我敢肯定,并非每个班级都需要访问application. 记住得墨忒耳定律。

如果你需要一些通用功能,比如将一个静态字符串转换为另一个静态字符串,我建议使用 php 的全局函数(而不是,例如,一个人造静态类(。 我相信它们是为此目的而设计的。

或者只是把它交给那些对它感兴趣的人。您提出的所有建议都像全局变量一样,即使您在 3 个变体中的 2 个中不这么称呼它。

在此之前:如果你想说"这是不可能的,因为一切都需要它",那么它可能做得太多,可以太多,和/或知道太多。