我什么时候应该使用静态方法


When should I use static methods?

我有一个包含10个方法的类我总是需要使用其中一种方法。现在我想知道,哪种方法更好?

class cls{
    public function func1(){}
    public function func2(){}
    .
    .
    public function func10(){}
}
$obj  = new cls;
$data = $obj->func3(); // it is random, it can be anything (func1, or func9 or ...)

class cls{
    public static function func1(){}
    public static function func2(){}
    .
    .
    public static function func10(){}
}
cls::func3(); // it is random, it can be anything (func1, or func9 or ...)

这是一个有趣的主题。我会给你一个以设计为导向的答案。

在我看来,在一个好的OOP体系结构中,永远不应该使用静态类/函数。

当您使用static时,这是在没有类实例的情况下调用函数。主要原因通常是表示一个不应该多次实例化的服务类。

我会给你3个解决方案(从最坏到最好)来实现这一点:

静态

静态类(只有静态函数)阻止您使用许多OOP特性,如继承、接口实现。如果你真的认为什么是静态函数,那么它是一个按类名称命名的函数。PHP中已经有了名称空间,为什么还要添加另一层呢?

另一个很大的缺点是,您无法定义静态类和使用它的类的明确依赖关系,这对应用程序的可维护性和可扩展性来说是一件坏事。

辛格尔顿

singleton是一种强制类只有一个实例的方法:

<?php
class Singleton {
    // Unique instance.
    private static $instance = null;
    // Private constructor prevent you from instancing the class with "new".
    private function __construct() {  
    }
    // Method to get the unique instance.
    public static function getInstance() {
        // Create the instance if it does not exist.
        if (!isset(self::$instance)) {
            self::$instance = new Singleton();  
        }
        // Return the unique instance.
        return self::$instance;
    }
}

这是一种更好的方法,因为您可以使用继承,接口和方法将在实例化的对象上调用。这意味着你可以定义契约,并与使用它的类使用低耦合。然而,有些人认为singleton是一种反模式,尤其是因为如果你想拥有两个或多个具有不同输入属性的类实例(比如连接到两个不同数据库的经典示例),你就必须使用singleton对所有代码进行大规模重构。

服务

服务是一个标准类的实例。这是一种合理化代码的方法。这种体系结构被称为SOA(面向服务的体系结构)。我举一个例子:

如果您想添加一个方法来向消费者销售商店中的产品,并且您有类ProductStoreConsumer。您应该在哪里实例化此方法?我可以保证,如果你认为今天这三节课中的一节课更合乎逻辑,那么明天可能会是其他课。这会导致大量重复,并且很难找到您要查找的代码。相反,您可以使用像SaleHandler这样的服务类,它将知道如何操作您的数据类。

最好使用一个框架来帮助您将它们相互注入(依赖注入),以便充分利用它们的潜力。在PHP社区中,您有一个在Symfony中实现这一点的好例子。


综上所述:

  • 如果你没有一个框架,单例当然是一个选择,即使我个人更喜欢一个简单的文件,在那里我进行手动依赖注入。

  • 如果你有一个框架,可以使用它的依赖项注入功能来做这种事情。

  • 您不应该使用静态方法(在OOP中)。如果您在某个类中需要一个静态方法,这意味着您可以创建一个包含此方法的新单例/服务,并将其注入到需要它的类的实例中。

答案取决于这些方法的作用。如果您使用它们来改变当前对象的状态,则需要使用实例方法调用。如果它们是独立的功能,那么您可以使用静态版本,但我会质疑它们为什么是类的一部分。

因此,static方法之间存在非常基本的差异。

要使用静态函数,不需要将类初始化为对象。例如,Math.pow(),这里的.pow()(在Java中;但解释仍然成立)是一个静态方法。

一般规则是使helper方法成为static

因此,例如,如果你有一个Math类,你不想用只帮助其他更重要的类的类来填充垃圾收集器。

如果你愿意的话,你可以把它用作动态初始化程序!

假设你有一个类RSAEncryptionHelper,现在你通常可以在没有任何参数的情况下初始化它,这将生成一个密钥大小为(比如)512位的对象;但是您还有一个重载的对象构造函数,它从其他类中获取所有属性:

$a = new RSAEncryptionHelper::fromPrimeSet(...);

在PHP类中,您可以使用class/methods/attributes:Abstract、Static、Private、Public等。。。最好的方法是知道如何根据需要将它们混合在一个类中,我将给你一个基本的例子:

Person类中,您有privatepublic方法,但您有一个名为"get_nationality"的方法,所以这是您在其他地方需要的函数,但您还没有安装Person类,因此,您将该方法设置为STATIC,这样您就可以在不安装任何Person类的情况下调用"get_nationality"方法,这将使您的业务模型更加优化,进而使CPU中的资源更加丰富。

静态函数也非常有用,但当我必须创建与类独立相关的函数时,我通常会生成特征

我不知道这种方法是否更好,但大多数时候我觉得它很有用。

只是在这里分享我的方法,这样我就可以更多地了解它的优点和缺点。

您可以认为是一家工厂。你会给出一些材料,它会给你同样的输出。然后您应该使用静态函数。

class ProductDetails
{
   public static function getRow($id, PDO $pdo): SingleProduct
   {
     // this function will return an Object. 
   }
}

我不是在这里定义Object。只要您需要一个单一产品,您就可以简单地执行ProductDetails::getRow(10, $pdo);