何时应使用静态方法?

2022-08-30 10:11:25

我有一个包含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 ...)

答案 1

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

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

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

我将为您提供3解决方案(从最差到最好)来实现这一目标:

静态的

静态类(仅包含静态函数)会阻止您使用许多 OOP 功能,如继承、接口实现。如果您真的想到什么是静态函数,那么它是一个由其类名称命名的函数。你已经在PHP中拥有命名空间,那么为什么要添加另一个层呢?

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

单身 人士

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

<?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;
    }
}

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

服务

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

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

使用一个框架来帮助你将它们相互注入(依赖注入)是一个好主意,以便充分发挥它们的潜力。例如,在PHP社区中,你有一个很好的例子,在Symfony中实现它。


总结一下:

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

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

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


答案 2

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


推荐