我有一个包含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 ...)
Run Code Online (Sandbox Code Playgroud)
要么
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 ...)
Run Code Online (Sandbox Code Playgroud)
Gnu*_*cki 60
这是一个有趣的主题.我会给你一个面向设计的答案.
在我看来,你绝不应该在一个好的OOP架构中使用静态类/函数.
当您使用静态时,这是调用没有该类实例的函数.主要原因通常是表示不应多次实例化的服务类.
我会给你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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一种更好的方法,因为您可以使用继承,接口和您的方法将在instanciated对象上调用.这意味着您可以使用它来定义合约并使用低级耦合.然而,有些人认为单例是一种反模式,特别是因为如果你想让你的类的2个或更多个实例具有不同的输入属性(比如连接到2个不同数据库的经典例子),你就不能没有对你所有的重构使用单例的代码.
服务
服务是标准类的实例.这是一种合理化代码的方法.这种架构称为SOA(面向服务的架构).我举个例子:
如果您想添加一种方法来将商店中的产品销售给消费者,并且您有类Product,Store并且Consumer.你应该在哪里实例化这个方法?我可以保证,如果你认为今天这三个课程中的一个更合乎逻辑,明天就可能是其他任何东西.这会导致大量重复,并且很难找到您要查找的代码的位置.相反,您可以使用类似于服务类的服务类SaleHandler,它将知道如何操作数据类.
最好使用一个框架来帮助您将它们注入彼此(依赖注入),以便充分发挥它们的作用.在PHP社区中,您可以在Symfony2中有一个很好的实现示例.
总结一下:
如果你没有框架,单身肯定是一个选项,即使我个人更喜欢一个简单的文件,我做手动依赖注入.
如果你有一个框架,使用它的依赖注入功能来做这种事情.
您不应该使用静态方法(在OOP中).如果你需要一个类中的静态方法,这意味着你可以创建一个包含这个方法的新单例/服务,并将它注入需要它的类的实例.
因此,在static方法上存在非常基本的差异。
要使用静态函数,您不需要将类初始化为对象。例如,Math.pow()这里.pow()(在 Java 中;但解释仍然成立)是一个静态方法。
一般规则是制作辅助方法static。
因此,例如,如果您有一个 Math 类,您不会想用只帮助其他更重要的类的类来填充垃圾收集器。
如果您愿意,您可以将其用作动态初始值设定项!
假设您有一个 class RSAEncryptionHelper,现在您通常可以在没有任何参数的情况下对其进行初始化,这将生成一个密钥大小为(例如)512位的对象;但是您还有一个重载的对象构造函数,它从其他类中获取所有属性:
$a = new RSAEncryptionHelper::fromPrimeSet(...);
Run Code Online (Sandbox Code Playgroud)
答案取决于这些方法的作用。如果使用它们来改变手头对象的状态,则需要使用实例方法调用。如果它们是独立的功能,那么您可以使用静态版本,但是我想问一问为什么它们完全属于类。