3

我是这个级别的 PHP 编程新手,我一直在阅读一篇关于单例和静态类的文章。我正在编写一个有助于我的数据库连接的类。

我遇到了 Jon Raphaelson 的以下代码(这里):

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 (!$this->db)                 // this line was modified due to comment
            $this->db = new PDO(...);       // this line was modified due to comment
        return $db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

似乎我找到了我要找的东西,但是我有几个问题。

  1. self::$factory = new ConnectionFactory(...);- 我在这个类中没有看到构造函数。我是否只是创建此构造函数并传入数据库详细信息('dbname'、'user'、'pass'等)?
  2. getSomething()函数,我假设目的是将所有将检索数据的实际函数放入 ConnectionFactory 类中 - 这就是该函数位于此类中的原因。否则,我会期望这个函数在另一个类中。[编辑] 跳过这个问题,我没有看到一个括号。
  3. 当两个用户登录站点并请求数据库连接(都在进行更新等)时会发生什么?这是一个单身人士会有问题吗?

谢谢!

4

3 回答 3

2

这主要是为了扩展我在问题下的评论......

更好的“单例”模式是这样的:

class ConnectionFactory {

    protected static $connection;

    public function getConnection() {
        if (!self::$connection) {
            self::$connection = new PDO(...);
        }
        return self::$connection;
    }

}

这个工厂的用户应该期待它的一个实例,而不是自己调用它:

class Foo {

    protected $connectionFactory;

    public function __construct(ConnectionFactory $factory) {
        $this->connectionFactory = $factory;
    }

    public function somethingThatNeedsAConnection() {
        $connection = $this->connectionFactory->getConnection();
        ...
    }

}

$foo = new Foo(new ConnectionFactory);

这允许Foo在需要时自行获取连接,但也允许您将一些替代连接注入到Foo中,例如用于测试目的。

作为一种便利措施并减少实例化复杂性,这种模式也很好:

class Foo {

    protected $connectionFactory;

    public function __construct(ConnectionFactory $factory = null) {
        if (!$factory) {
            $factory = new ConnectionFactory;
        }
        $this->connectionFactory = $factory;
    }

    ...

}

这仍然允许注入和覆盖依赖项,但它不需要您每次实例化时都注入工厂Foo

于 2012-11-14T16:05:47.177 回答
0
  1. 一个类不需要显式构造函数就可以用new ClassName(). 但是,如果该类应该是一个单例(在这种情况下看起来像),那么该模式的全部意义在于使此类实例化无法从类外部进行,这就是为什么我认为应该使用声明的构造函数private关键词。

  2. getgetSomething()是一个“独立”函数,带有使用您的类的示例。

  3. 不可以。多个用户使用多个 PHP 实例来处理您的脚本,并且他们之间没有共享任何内容。

于 2012-11-14T15:27:28.313 回答
0

工厂是单身,因为您不想要多个工厂。

  1. 您不需要构造函数,您可以通过 getFactory() 方法设置工厂所需的任何状态。getFactory() 函数没有得到连接,所以不要在这里做任何与连接相关的设置,而不是连接对象本身。工厂“构建实例”供您使用,因此您可以使用 getConnection() 方法设置状态并构造工厂应该生成的连接对象。
  2. getSomething() 不是 ConnectionFactory 类中的方法,它只是使用工厂类获取工厂,然后获取连接的示例。

我个人讨厌 PHP 中的方法链。getSomething() 中真正发生的事情是:

function getSomething()
{
   $factory = ConnectionFactory::getFactory();
   $conn = $factory->getConnection();
   .
   .
   . 
}
于 2012-11-14T15:20:21.550 回答