Tuesday, July 1, 2008

Singleton Patterns in PHP 5

The Singleton Pattern is one of the few things I really like from Design Patterns. While the original Gang of Four book has some very good stuff in it, later works seem like Software Industry Marketing Fluff [SIMF] - but I've already bitched about that.

The Singleton is GREAT because it can replace Global Variables - if not everywhere, at least in a lot of important cases.

In case you don't know what a Singleton is, it's an Object which has only one instance. Ideally, you would like to write something like
$foo = new Thing();
and get a reference to the one instance of Thing.

The "normal" way to implement the Singleton Pattern is to hack up the class definition in an unnatural way:
  • Disable the normal constructor by making it private
  • Define a class variable to hold the One Instance
  • Create a different public function which is used to instantiate the first instance and return it on all subsequent 'instantiations'
This is because none of the Object Oriented Languages directly support Singleton - except Ruby which has a Singleton base class so you can create them by normal inheritance.

I was so taken with Ruby's Singleton base class, I decided to write one in PHP 5.

Drum Roll........

Didn't work. Failed Miserably.

It turns out that in PHP 5.2 static class variables [that is, Class Variables] are always in the base class. I won't go into that here. Instead, take a look at this test I wrote.

Anyway, just because we can't build a base class for Singleton Objects, doesn't mean we can't clean up their creation. Here is an example of a pseudo-Singleton which allows me to write
$foo = new Thing();

and have a $foo object which acts just like a Singleton even though it has many instances.

The reason this works is that we don't need a single instance of the Object. What we need is a reference which returns the common data, where the methods act on the common data, where modification of the common data is seen by all existing references.

The Pseudo-Singleton looks, acts, and smells like a Singleton, except it is more convenient and natural to use.

The only thing better would be a 'singleton' keyword prefix to use in 'class' definitions.