The Singleton is a Design Pattern primarily designed to allow only one instance (one object) of a single class to be substantiated at any given time. The main reason one would want to do this is when it makes absolutely critical sense for there to be only one Object of a particular type in an application.

The Singleton Design Pattern is by far one of the most abused design patterns. Frequently, people who don’t know better will use them in places where they seem to fit, only to later find out that their usage was totally inappropriate.

CHANGING A CLASS FROM A SINGLETON TO A REGULAR CLASS IS FAR HARDER THAN ONE WOULD THINK. Because of this, you must be absolutely sure that your application or library would NEVER POSSIBLY work at all or make any sense at all having multiple objects of the same class.

Examples of inappropriate Singleton classes include: * Transaction class - Sure you may think you’re only ever going to have one transaction at a time, but what happens if you want to add support for multiple credit card transactions? Or split a gift card with a credit card? Screwed. That’s what. * Database drivers - Only one database object/connection is great, right?? Just wait until your app needs to access another database, or you want to add replication. Ouch, now you have to rewrite your entire app!

The point of the examples is even though things may seemingly make sense to run isolation, they almost never work out that way in practice. Thus you have to be extremely careful and think “big picture” before you ever make a class a singleton. A good rule of thumb is to use the singleton ONLY when you want to guard against serious complications with two or more objects existing at the same time.

Examples of appropriate Singleton classes would include

  • Factory classes. Generally there is never a need and many times a valid risk to having multiple objects for your factories. Thus, these are almost always best as singletons or complete static classes.
  • Payment gateways: While you might want multiple transactions, you probably don’t want Hosea’s card to be charged twice, accidentally, by two inappropriately-created payment gateway interfaces, and the chances of needing to use two different payment gateways, simultaneously, are in fact quite rare.
  • Exchanges or anything needing Transactional Integrity: Related to payment gateways, any object that should not have competitors in order to guarantee consistency may also be a candidate for a singleton.

Anatomy of a Singleton

class Singleton
    // All Singleton classes must have a private instance variable to hold the only
    // object that will exist. It has to be static.
    private static $instance;
    // All Singleton classes will have private constructors to prohibit willy-nilly creation of 
    // objects.
    private function __construct()
        // It is very important to make this private.
    // The main way to access singletons is via a getInstance public function.
    // This is commonly abbreviated as getI()
    public static function getInstance()
        // 1. Determine if the object doesn't exist.
        if (is_null($this->instance))
            // 2. Create and set the instance.
            $this->instance = new Singleton;
        // 3. You are now guaranteed to have a Singleton object. Return it.
        return $this->instance;