【发布时间】:2012-11-14 15:14:54
【问题描述】:
我是这个级别的 PHP 编程新手,我一直在阅读一篇关于单例和静态类的文章。我正在编写一个有助于我的数据库连接的类。
我遇到了 Jon Raphaelson (here) 编写的以下代码:
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();
.
.
.
}
我好像找到了我要找的东西,但是我有几个问题。
-
self::$factory = new ConnectionFactory(...);- 我在这个类中没有看到构造函数。我是否只是创建此构造函数并传入数据库详细信息('dbname'、'user'、'pass'等)? -
getSomething()函数,我假设其目的是将所有将检索数据的实际函数放入 ConnectionFactory 类中 - 这就是该函数位于此类中的原因。否则,我会期望这个函数在另一个类中。 [编辑] 跳过这个问题,我没有看到一个括号。 - 当两个用户登录站点并请求数据库连接(都在进行更新等)时会发生什么?这是一个单身人士会有问题吗?
谢谢!
【问题讨论】:
-
我建议不要使用这种模式。请参阅How Not To Kill Your Testability Using Statics 了解原因和替代方案。
-
@deceze 您是否建议 PHP 中的人不要使用工厂模式或单例模式?我不确定我明白为什么这些本质上是不好的——它们是经过严格审查的 OOP 模式。
-
@Ray 我提倡反对单例模式,更具体地说反对在任何地方静态调用
ConnectionFactory::getFactory()。如果您使用的是工厂,则该工厂应作为对象注入,而不是静态调用。单件工厂是毫无意义的。应该使用工厂来为对象 A 提供构造其他对象 B 的方法,而无需将 A 静态耦合到 B。因此,将 A 静态耦合到工厂 B 没有任何优势。 -
@deceze 您将如何强制不创建工厂或连接的多个副本?说资源有限的东西,例如与数据库的连接,您或使用您的代码的人可能会意外创建比可用连接更多的连接。的确,它是更可测试的方法和类,但这样做也更有可能创建单元测试可以愉快地工作的情况,但是当预期的连接被拒绝或由于资源争用而超时时,整个代码会中断。
-
@Ray 将实例化的连接保存为工厂的
static属性。您可以根据需要实例化任意数量的工厂,但它们都只会分配一个连接。更好的是,只在调用链中的某个位置创建一次连接,然后使用依赖注入将其传递给每个需要它的对象。