全局函数 vs 函数 vs 静态类方法

5
假设您有一个独特的对象,它被所有其他类和函数使用...像$application这样。
在您的函数中如何访问此对象?
  1. using a global variable in each of you functions:

    global $application;
    $application->doStuff();
    
  2. creating a function, like application() that instantiates the object into a static variable and returns it; then use this function everywhere you need to access the object:

    application()->doStuff();
    
  3. create a singleton thing, like a static method inside the object class which returns the only instance, and use this method to access the object:

    Application::getInstance()->doStuff();
    
  4. KingCrunch & skwee: Pass the application object as argument to each function/class where is needed

    ...
    public function __construct(Application $app, ...){
      ....
    
如果有其他选项,请发帖分享。我想知道这些选项中哪一个最有效率/被认为是“最佳实践”。

2
你有具体的问题吗,还是只是想列个清单? - user142162
3个回答

4
我会将其传递给所有需要的方法。 例如:
function doFoo(Application $app) {
    $app->doStuff();
}

全局变量和单例被认为是不好的,会使你的代码过于耦合,这会使单元测试更加困难。只有当你回答“是”时才允许使用单例模式,且需要满足以下条件:

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

如果你对所有三个条件都回答“是”,那么你可以使用单例模式。在任何其他情况下,只需将所有实例传递给需要它们的所有方法即可。如果你有太多实例,请考虑使用类似Context的东西。
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。

祝好运!


2(我必须拥有给定对象的单个实例)有点真 :) - Alex
但是如果有多个实例会导致程序错误吗?这是一个逻辑语句A && B && C,你的情况下B为真而A和C为假,所以该语句为假:)我真的想不到这个语句会成立的情况。也许在编程某种微控制器时,我只有一个CPU或类似的情况下会出现这种情况... - Dmitry Kudryavtsev

4
单例、上帝类、单体类等都是反模式,因此我建议第四种选择:依赖注入。您可以通过工厂(或者甚至是new,如果它没有依赖关系,但这可能会在以后复杂化)在应用程序中创建一个application实例。
然后,任何需要访问application的类都可以作为成员变量通过构造函数方便地获取它。我相信不是每个类都需要访问application。请记住迪米特法则。
如果您需要一些通用功能,例如将一个静态字符串转换为另一个字符串,我建议使用php的全局函数(而不是伪静态类)。我认为它们就是为了那个目的而设计的。

1

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

在此之前:如果你想说“那不可能,因为一切都需要它”,那么也许它做得太多了,可以做得更少,和/或者知道得太多了。


这是正确的,我可以将应用程序作为参数传递给需要它的每个类的__construct。但是我不知道...在该类中使用$this->application看起来有点奇怪。 - Alex
我还需要将该参数传递给类的每个静态方法... - Alex
使用$this->property看起来就像访问依赖项的样子。关于您的第二个评论:听起来您有太多的静态方法了。 - KingCrunch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接