Singletons aren’t always that single…

In: Design Pattern| PHP| Singleton

17 May 2009

I have decided to write a serie of posts around the Singleton design pattern. This first one will discuss the uniqueness aspect of a Singleton.

What is a Singleton again ?

In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. (Wikipedia)

Here is a typical implementation of a Singleton class in PHP. You will see this kind of code in many different existing frameworks.

/**
 * A typical implementation of a Singleton
 */
class aSingleton
{
    private static $_instance = null;

    public $foo = null;

    private function __construct()
    {
    }

    public static function getInstance()
    {
        if(null === self::$_instance)
        {
            self::$_instance = new aSingleton();
        }

        return self::$_instance;
    }
}

So, is there anything wrong with that code ?

One of the things that I really dislike about this implementation (there are actually many others things I dislike about Singleton, but I will discuss them in others posts), is the fact you cannot (actually this isnt necessarily true as we will see later) have two different instances of a Singleton. I dont understand why a class should enforce a such rule / constraint. Why would someone want to have a such constraint ? What good would it make ?

Some may argue that sometimes in an application, you want to keep using the same instance of an object. Usually, they will say that objects like a logger,  a configuration or a database handler are good candidates for a such use. Well, that’s fine with me, but why do I have to use a Singleton for that ? Is this really the best solution to do that ?

Let’s use a parrallel. Imagine, we need to always use the same hammer to do a job for some good reason.  So, we decide you are going to enforce that requirement, by destroying all the others existing hammers and any shop / factory selling or producing hammers. That way, when we use a hammer, we are sure it is the same one (it is the only hammer that exist in the whole universe and it is impossible that for any other hammer to get built).

Doesn’t that sound crazy and  extreme ? I mean, why wouldn’t we just mark that hammer (write a name on it or something) and just store it in a specific place, so we know where to get it and we can ensure that we are using the same hammer. Also, if one day we do need to have another hammer, well we would be able to…

There is also a problem with most existing implementations of a Singleton.  The design pattern is supposed to enforce the number of different instance of a particular class, right ? Well, there are ways to bypass that and end up with different instances of a Singleton.

In PHP, we could use the clone construct.

$a = aSingleton::getInstance();
$a->foo = 10;

$b = clone $a;
$b->foo = 20;

echo $a->foo . PHP_EOL; // Display 10
echo $b->foo . PHP_EOL; // Display 20.
                        // Damn this isnt anymore my Singleton!

To prevent that, we would need to implement the __clone() method (define it as final and throw some kind of exception whenever called). This would  solve the issue with the clone construct.

Well, that still won’t completely prevent someone from being able to have two different instances of our Singleton. Someone could still use the serialization. Look at this code.

$a = aSingleton::getInstance();
$a->foo = 10;

$str = serialize($a);
$b = unserialize($str);
$b->foo = 20;

echo $a->foo . PHP_EOL; // Display 10
echo $b->foo . PHP_EOL; // Display 20.
                        // Damn this isnt anymore my Singleton!

Again, to prevent that, we could implement the __wakeup() method (also declare it as final and throw some kind of exception).

So, we just added a new constraint on the class : We cannot unserialize it anymore via the unserialize function. If we cannot unserialize, then we made serialization pretty much useless…

That’s the end of this first post on Singleton. I am hoping that after reading this, you already feel (if you are a Singleton adept) that there might be something wrong or bad using this design pattern.

My next post will discuss other aspects that I really dislike about Singleton, such as how to unit test Singleton, why Singleton is a global state and why global states are bad, etc.

  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks

Comment Form

Who am I?

My name is Bashar Al-Fallouji, I work as a Enterprise Solutions Architect at Amazon Web Services (Sydney, Australia).

I am particularly interested in Cloud Computing, Web applications, Open Source Development, Software Engineering, Information Architecture, Unit Testing, XP/Agile development, etc.

On this blog, you will find mostly technical articles and thoughts around PHP, OOP, OOD, Unit Testing, etc. I am also sharing a few open source tools and scripts.

  • dipan: Hi Bashar It's really awesome that you wrote this code. IT'll save tones of time of all developer. [...]
  • Bashar: Glad that you liked it ! [...]
  • Angel S. Moreno: well, there goes wasting a couple of hours of development and a couple of days of testing. I owe you [...]
  • Bashar: Thats right, the setSaveFile create a files containing an associative array of classname => filen [...]
  • Loggy: Jim's clarification in particular was pretty useful although I did have to dig down into the tree to [...]