3

这是一个基本的类构造,在使用 DI 之前(我知道,它的结构有点不正确,请尽量集中在问题上)

class Mobile
{
    public function getWeight()
    {
        return 4;
    }
}

class User
{
    public static function getWeight()
    {
        $mobile = new Mobile();
        return $mobile->getWeight();
    }
}

续订后,使用 DI:

class User
{
    public $mobile;

    public function getWeight()
    {
        return $this->mobile->getWeight();
    }
}

如果我们检查一下,由于它是静态的,getWeight()因此不需要拥有的实例User- 创建它的实例毫无意义。但是现在,getWeight()不能是静态的,所以无论如何都需要一个实例 - 只是因为依赖注入!当然,我知道这个例子有点蹩脚——我只是想指出依赖注入杀死静态方法的逻辑,但有时静态方法需要,因为拥有一个类的实例毫无意义,想想 JAVAMath.max()方法。如何解决?

4

1 回答 1

6

是的,依赖注入使静态方法变得不必要,但是您看不到它的原因是因为您的示例选择不当。

静态方法仍然有用。但它们不应该在应用程序的构造根点之外使用。

这个构造根是什么?每个应用程序都始于一个静态的全球世界。$_SERVER、$_GET 和 $_POST 中有请求信息,还有一个请求的 URL,它要么在中央文件中处理,要么指向各自的脚本文件。

然后我们实现了模型、业务逻辑、用于表单验证的实用程序对象、模板等——如果做得好,这些都没有静态方法,但都需要实例化。

这没问题,因为它们都被实例化了——可能在依赖注入容器的帮助下。所以构造根是好对象的实例世界与每个请求的静态全局世界相遇的地方。确定会议发生的确切层是一个很好的做法,即在该点之外不应有静态呼叫。

本质上:如果您能够使用 DI 容器,您将在静态全局世界中配置它,然后,可能在控制器中,向它请求一个对象。这将创建所有需要的子对象,根据需要将它们全部注入彼此,并仅返回您请求的主对象的一个​​实例。而且您无需担心如何注入所有这些其他对象 - 它们已经存在。

最后一句话:为什么静态调用不好?因为它们将这个调用与使用的类静态链接。您不能仅通过传递实现相同接口的不同对象或从相同父对象继承来简单地用另一个类替换此调用。您必须更改代码。

而您的 Java 示例Math.max()则是另一种情况。在 PHP 中,这甚至不是一个对象,而只是一个全局函数。它之所以有效,是因为此函数不适用于任何对象实例——输入数据明确定义了函数的输出。

但是不要错误地定义您创建的每个方法,这些方法仅适用于输入参数并以静态形式返回输出。如果你有一个对象,享受它。:)

于 2013-10-20T15:16:15.873 回答