解释这种单例工厂模式


Explain this singleton factory pattern

class ConnectionFactory
{
    private static $factory;
    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }
    private $db;
    public function getConnection() {
        if (!$db)
            $db = new PDO(...);
        return $db;
    }
}
function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

有几件事我没有得到

  1. 当我说"可以在不启动类的情况下访问类的静态属性"时,我是否正确
  2. !db做什么
  3. 这是怎么回事ConnectionFactory::getFactory()->getConnection();
  4. 有人可以解释getFactory方法
  1. 你就在这里。
  2. ! 是不是。这意味着如果$db为假,则对其进行初始化。由于它在静态方法中,它将保持初始化状态,下次从第二次开始将返回存在的$db!$db == false。
  3. 就像$db一样,它正在检查$factory的实例是否存在,如果没有创建一个实例并返回它,否则返回现有的实例。

4.

public static function getFactory()
{
     if (!self::$factory) // is self::$factory initialised?
            self::$factory = new ConnectionFactory(...); //initialise it
     return self::$factory; //return self::$factory
}

同样在这里$factory似乎是一个设置在某处的变量。据推测,它可以包含几个不同的类名。不会更改函数的工作方式。它是单例模式

添加有关此模式的有趣链接 维基百科

对于 1. 是的,始终可以使用 ClassName::$staticvarname 访问类的静态属性

对于 2. 这里肯定有一个错误。 它应该是 if(!$this->db(,getConnection 中的所有代码都应该使用 $this->db 而不是 $db。

getFactory(( 是 Singleton 模式中更标准的 getInstance(( 的"别名"。如果存在,它返回类的单个实例,如果不存在,则创建单个实例。

getFactory((->getConnection(( 调用很简单:getFactory(( 返回 ConnectionFactory 类的单个实例。因此,现在您已经有了单一实例,可以对其执行任何调用。getConnection(( 返回由单例(存储在 $db 成员中(处理的"单个"PDO 实例

  1. 正确
  2. ! 是 NOT 运算符。基本上如果(!$db(表示如果$db为空,则执行if块
  3. Get factory 是一个返回 ConnectionFactory 的(单个(实例的函数,这个实例有一个函数 getConnection((
  4. 在单例模式中,只应存在类的单个实例,该实例是类本身的私有静态成员。getFactory(( 函数是获取对这个单个实例的引用的方法(如果实例为 null,它首先初始化实例(。
  1. 是的,static 表示对于请求它的每个对象,它将是相同的值,因此不需要实例化
  2. ! 表示NOT。它通常被视为 !=,表示NOT EQUAL 。在这种情况下,正在检查它以查找是否已创建 db 对象,因此这意味着 db NOT NULL

3和4。您指定的方法表示使用该类(不实例化它(,并调用 getFactory((。如果NOT NULL,这将创建因子,否则,它将返回已创建的工厂。之后,它使用返回的工厂instance请求连接。由于只有一个工厂,那么我们可以假设一旦连接被实例化(与工厂被实例化的方式相同(,那么该连接将可用于工厂的所有用途

我建议阅读维基百科关于单例模式的文章。希望这会有用。另外,请记住,一般来说,单例模式被认为更像是一种应该避免的反模式。在我看来,这个类可以很容易地创建为具有getConnection静态方法的静态类。显示代码后,似乎在这里创建自己的毫无意义。但是,这只是在这个小背景下。