小编典典

是否存在用PHP访问数据库的单例的用例?

design-pattern

我通过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中缺少单例的用例?


阅读 340

收藏
2020-07-30

共1个答案

小编典典

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

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

When this happens, if you have used a static class you’re in for a much worse
refactor than if you had used a singleton. A singleton is an iffy pattern in
itself, but it converts fairly easily to an intelligent factory pattern–can
even be converted to use dependency injection without too much trouble. For
instance, if your singleton is gotten through getInstance(), you can pretty
easily change that to getInstance(databaseName) and allow for multiple
databases–no other code changes.

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

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

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

2020-07-30