views:

327

answers:

1

What is the best method for using singleton design pattern in conjunction with the factory method pattern in PHP5? My simplest usage scenario for this is instantiation selective database connection only once for each database type.

+5  A: 

singleton factory for DB connection:

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
            //...
        }
    }
}

usage:

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

Singletons are not really needed anymore because all methods can be called statically... But the database classes can still be considered singletons because there will only be one single instance of them in your application.

So the same effect is created by using the factory and registry patterns.

The registry could be replaced by making your database classes singletons then the factory would look like this:

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;
    }
}

So you have the choice of making all your DB objects singletons or using a registry. I personally would go with a registry because it can be used to store any types of object, even the ones where you don't want to make the class a singleton.

Design choices are always subjected to personal flavor imo...

Nicky De Maeyer
Singletons are sooo much more l33t than old-school static classes, though :-]
Atli
and because they are "l337" you will use them where you do not need them?
Nicky De Maeyer
No of course not. Was more of a joke than anything else. I have to wonder, though, what the difference between the two methods really is in terms of performance, if any. - Going to have to do a bit of research into that.
Atli
@Nicky De MaeyerAlthough your code explains singleton factory well, I am looking for a solution that makes using multiple database connections in the same application instance possible. Also, your code returns a new copy of object instance every time, isn't it resource intensive?
eyazici
when initializing the DB you could store the connection inside some kind of Static registry, I'll update the code
Nicky De Maeyer