Difference between singleton and factory pattern

Singleton Factory
Returns Same instance Returns various new instances
Single Constructor hiding Multiple Constructors expose
No interface Interface driven
No Subclasses Subclasses

Singleton

The singleton pattern is an often used pattern in many applications when only a single instance of a resource is required. The most obvious type of resource for PHP web pages is a database connection, although other resource types can be used. When fetching or dynamically creating a web page several database calls may need to be made. If a single instance of the resource could be used, rather than creating several connections, the overhead is minimized. The single instance in this case, is created by the singleton pattern.

<?php
class db {
    /*** Declare instance ***/
    private static $instance = NULL;
    
    /**
     * the constructor is set to private so
     * so nobody can create a new instance using new
     */
    private function __construct() {
        /*** maybe set the db name here later ***/
    }

    /**
     * Return DB instance or create intitial connection
     *  @return object (PDO)
     * @access public
     */
    public static function getInstance() {
        if (!self::$instance) {
            self::$instance = new PDO("mysql:host='localhost';dbname='animals'", 'username', 'password');
            self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        return self::$instance;
    }
    /**
     * Like the constructor, we make __clone private
     * so nobody can clone the instance
     */
    private function __clone() {

    }
} /*** end of class ***/
?>

Lets look at what has happened in the singleton class above. A variable name $instance is created and made private, this ensures nobody and try to access it directly. Similarly, the constructor and __clone methods have been made private to prevent cloning of the class, or of somebody trying to instantiate an instance of it. The class has a single method for providing a resource, the getInstance() method.

The getInstance() method checks that an instance does not already exist. If no instance exists a new instance of the PDO class is created and assigned to the $instance variable. If an existing instance is available, the getInstance() method returns this. The result is that the returned value is always the same instance, and no new resource, or overhead, is required.

Here is a small demonstration of how this might be used in an application.

<?php
try {
    /*** query the database ***/
    $result = DB::getInstance()->query("SELECT animal_type, animal_name FROM animals");

    /*** loop over the results ***/
    foreach ($result as $row) {
        print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
    }
} catch (PDOException $e) {
    echo $e->getMessage();
}
?>

Factory

The factory pattern is a class that creates objects for you, rather than you needing to use the new keyword to create one yourself. The factory is, as the name suggests, a factory for creating objects. Why do we need this? Lets consider an application that uses an ini file for configuration option. Then the application is changed to gain the configuration options from a database. The rest of the application falls apart like a house of cards as the base is removed. This "tight coupling" of objects, where each object relies heavily on another, creates problems in larger applications. A system is needed where objects can reference each other, but are not inter dependent.
In our example of the configuration file becoming a database, if other classes were dependent on the class that read from the ini file, and this was suddenly tasked to the database class problems occur.
By using the factory design pattern, if you change the type of object from the ini reader class to the database class you only need to change the factory. Any other code that uses the factory will be updated automatically.

<?php
/**
 * @config interface
 */
interface Config {
    function getName();
}

/**
 * @config class
 */
class userConfig implements Config {
    /*
     * @username
     */
     public $user_id;

     /*** contructor is empty ***/
     public function __construct($id) {
        $this->user_id = $id;
     }

     public static function Load($id) {
        return new userConfig($id);
     }

     public function getName() {
         try {
             /*** query the database ***/
             $sql = "SELECT username FROM user_table WHERE user_id=:user_id";
             $db = db::getInstance();
             $stmt = $db->prepare($sql)
             $stmt->bindParam(':user_id', $this->user_id, PDO::PARAM_INT);
             return $stmt->fetch(PDO::FETCH_COLUMN);    
        } catch (PDOException $e) {
            /*** handle exception here ***/
            return false;
        }
    }
} /*** end of class ***/

/*** returns instance of config ***/
$conf = userConfig::Load( 1 );
echo $conf->getName();
?> 

This might seem a little excessive code for simply retrieving a username. But in large-scale application where a change from file based to database retrieval is made, the results could be catastrophic. Here its is simply a matter of changing the the getName() method retrieves the name, and the returned object is the same, thus allowing other parts of the application that require the username, eg: a login for a cart, to continue as they did previously.


A singleton pattern ensures that you always get back the same instance of whatever type you are retrieving, whereas the factory pattern generally gives you a different instance of each type.

The purpose of the singleton is where you want all calls to go through the same instance. An example of this might be a class that manages a disk cache, or gets data from a static dictionary; wherever it is important only one known instance interacts with the resource. This does make it less scalable.

The purpose of the factory is to create and return new instances. Often, these won't actually be the same type at all, but they will be implementations of the same base class. However, there may be many instances of each type