【问题标题】:Singleton in Conjunction with the Factory Pattern in PHP5单例与 PHP5 中的工厂模式结合
【发布时间】:2009-11-30 06:42:29
【问题描述】:

在 PHP5 中结合使用单例设计模式和工厂方法模式的最佳方法是什么?我最简单的使用场景是每个数据库类型只实例化一次选择性数据库连接。

【问题讨论】:

  • 您是否在寻找示例实现或实现这些模式的方法?
  • 不,我正在寻找这些模式的有效(在速度方面)实现。我知道没有确定的答案,但我相信最好的方法是改进某些东西,学习其他人的做法。

标签: php design-patterns singleton factory-pattern


【解决方案1】:

用于数据库连接的单一工厂:

class Registry
{
    private static $_objects;

    public static function set($key, $object)
    {
        if (!array_key_exists($key, self::$_objects)) self::$_objects[$key] = $object;
    }

    public static function get($key)
    {
        if (array_key_exists($key, self::$_objects)) return self::$_objects[$key];
        else return false;
    }
}

class DBFactory
{
    public static function getConnection($type)
    {
        switch ($type) {
            case 'pdo':
                if (!(Registry::get('DB_PDO') instaceof DbPdo)) Registry::set('DB_PDO', new DbPdo('user', 'pass', ...));
                return Registry::get('DB_PDO')
            case 'mssql':
                //same for other connections
            //...
        }
    }
}

用法:

$factory = DBFactory::getConnection('pdo');

不再需要单例,因为所有方法都可以静态调用... 但是数据库类仍然可以被视为单例,因为在您的应用程序中只会有它们的一个实例。

因此使用工厂模式和注册表模式可以创建相同的效果。

可以通过将数据库类设为单例来替换注册表,然后工厂将如下所示:

class DBFactory
{
    public static function getConnection($type)
    {
        switch ($type) {
            case 'pdo':
                return DbPdo::getInstance('user', 'pass', ...);
            case 'mssql':
                //same for other connections
            //...
        }
    }
}

class DbPdo
{
    private static $_instance;

    private function __construct($user, $pass, ...){ //instantiate object }

    public static function getInstance($user = null, $pass = null, ...)
    {
        if (!(self::$_instance instanceof DbPdo)) self::$_instance = new DbPdo($user, $pass, ...);
        return self::$_instance;
    }
}

因此,您可以选择将所有数据库对象设为单例或使用注册表。我个人会使用注册表,因为它可以用来存储任何类型的对象,甚至是那些你不想让类成为单例的对象。

设计选择总是受制于个人风格...

【讨论】:

  • Singleton 比老式的静态类要多得多 :-]
  • 因为它们是“l337”,所以你会在不需要它们的地方使用它们?
  • 不,当然不是。这更像是一个笑话。不过,我不得不想知道,这两种方法在性能方面的真正区别是什么,如果有的话。 - 必须对此进行一些研究。
  • @Nicky De Maeyer 虽然您的代码很好地解释了单例工厂,但我正在寻找一种解决方案,可以在同一个应用程序实例中使用多个数据库连接。另外,您的代码每次都返回一个新的对象实例副本,这不是资源密集型的吗?
  • 初始化数据库时,您可以将连接存储在某种静态注册表中,我将更新代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
相关资源
最近更新 更多