返回实例变量V / s返回直接对象

时间:2013-03-05 06:07:03

标签: php static-members

我正在研究2009年建立的网站的源代码,它是一个自定义框架。

有什么区别?

<?php
class DbAccess {

    private static $instance;

    /**
     * Returns the instance of the DB Class
     */

    public static function getInstance()
    {
        self::$instance = new DbAccess();
        return self::$instance;
    }
}

V /秒

<?php
class DbAccess {


    /**
     * Returns the instance of the DB Class
     */

    public static function getInstance()
    {
        return new DbAccess();
    }

}

我已经开发了几个定制框架和一组具有不同模式的库,但有时,我看到返回实例的方法是通过self::$instance,有时,它直接通过{{返回1}}

哪个好习惯?考虑即将推出的PHP版本。

3 个答案:

答案 0 :(得分:5)

谈论OOP时,两者都不是好习惯。其他人已经指出的第一种方法看起来像有人试图实现单例模式而失败了。就OOP而言,单身人士有多糟糕。它引入了紧耦合,隐藏依赖和全局状态。基本上它只是一种使用the global keyword的奇特方式。

现在是你的第二个例子。具有完全相同的缺点基本上是相同的。

注意,每次调用该方法时,这两个示例都会创建一个新的数据库连接。哪个......不是最佳的。

现在我要做的就是以下内容(使用dependency injection):

假设您有一些需要数据库访问的类,您可以执行以下操作:

class Foo
{
    private $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function methodWhichNeedsDatabaseAccess()
    {
        // do something with $this->db
    }

}

// or whatever instance for database access you are using
$db = new PDO(dsn);
$foo = new Foo($db);
$foo->methodWhichNeedsDatabaseAccess();

答案 1 :(得分:0)

静态函数都返回对象的新实例。第一个示例允许您将来再次静态引用该实例,尽管它存储在私有静态中,因此只能从该类中的成员(函数)访问它。

答案 2 :(得分:0)

第一个示例看起来像singleton的示例,但是,它没有包含在典型的if exists包装器中。当您只想创建一个类的实例时,单例是很好的做法:

public static function getInstance() {
  if (!isset(self::$instance))
    self::$instance = new DbAccess();
  return self::$instance;
}

这样做的方式是你只能通过那个实例访问这个类(这样你就不会打开到同一个数据库的多个连接)。

如果他们想控制构造函数,他们可能会遵循第二种模式。您可以将构造函数设为私有(以便只有该类可以调用构造函数并创建新对象)。这在factories中很常见。