小编典典

在PHP中是否有用于数据库访问的单例的用例?

php

我通过PDO访问我的MySQL数据库。我正在设置对数据库的访问,而我的第一次尝试是使用以下内容:

我想到的第一件事是global

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');

function some_function() {
    global $db;
    $db->query('...');
}

这被认为是不好的做法。稍作搜索后,我得到了Singleton模式,该模式

“适用于需要一个类的单个实例的情况。”

根据手册中的示例,我们应该这样做:

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }
}

function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');
}

some_function();

为什么我需要这个相对较大的课程?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }
}

function some_function() {
    Database::get()->query('...');
}

some_function();

最后一个效果很好,我不必担心$db了。

如何创建较小的单例类,或者在PHP中缺少单例的用例?


阅读 482

收藏
2020-05-26

共1个答案

小编典典

好的,当我刚开始我的职业生涯时,我想了一下。以不同的方式实现它,并提出了两个选择不使用静态类的理由,但它们是相当大的。

一种是,您会发现很多时候,您绝对可以确定自己永远不会有一个以上的实例,而最终又会有一个实例。您可能最终会得到第二个监视器,第二个数据库,第二个服务器(无论如何)。

发生这种情况时,如果您使用静态类,则与使用单例相比,您的重构困难得多。单例本身就是一个不稳定的模式,但是它很容易转换为智能工厂模式-
甚至可以转换为使用依赖注入而不会带来太多麻烦。例如,如果您的单例是通过getInstance()获得的,则可以轻松地将其更改为getInstance(databaseName)并允许多个数据库-
无需更改其他代码。

第二个问题是测试(老实说,这与第一个问题相同)。有时您想用模拟数据库替换数据库。实际上,这是数据库对象的第二个实例。使用静态类比单例要困难得多,您只需要模拟getInstance()方法,而不是模拟静态类中的每个方法(在某些语言中可能会非常困难)。

这实际上归结为习惯-当人们说“全球”很糟糕时,他们有很好的理由这么说,但是在您亲自解决问题之前,它可能并不总是显而易见的。

您可以做的最好的事情是(像您一样)提出问题,然后做出选择并观察决定的后果。与一开始就正确地掌握代码相比,掌握随着时间的推移解释代码演变的知识更为重要。

2020-05-26