2009.01.27

Often one of the first patterns that young developers encounter, the singleton, solves a very sloppy, dangerous, and nightmarish practice known as global variables. There are components in nearly every application that need to be accessed everywhere. Configuration variables are a perfect example of this. The younger developers might be tempted to declare a debug variable as global, and just access it where he/she pleases. You will learn later on in the project that this makes maintaining the application very frustrating.

What's wrong with global variables? I'm not going to spend much time on the subject. Here is an excerpt from the wikipedia page on Global Variables:

They are usually considered bad practice precisely because of their nonlocality: a global variable can potentially be modified from anywhere, (unless they reside in protected memory) and any part of the program may depend on it. A global variable therefore has an unlimited potential for creating mutual dependencies, and adding mutual dependencies increases complexity.

The Problem

If you haven't already, read my introductory article in this series where I discuss the general ideas behind patterns.

Moving on, let's assume that our application has a Config class that stores the application's preference-related values. Naturally, these values will need to be accessed from god knows how many other classes in the application. Instantiating the Config class over and over again is costly and unnecessary. On top of that, what if you need to dynamically set a new config variable from class A that is referenced in class B? Since each instance of Config is separate from all the others, this would be impossible.

Please note: I will be using php5 code for my examples.

As you can see, each instance of Config is separate from the others. Changing the member property on one instance of the class, does not change it for all the others. How can this problem be solved by retaining the seemingly usefulness of global variables while keeping to object-oriented programming's strict standards?

The Solution

Enter: The Singleton.

The singleton pattern allows us to retain the same instance of a class no matter how many times it is 'instantiated'. I put instantiated in quotes because that's not exactly true. It behaves very much like a global variable. If you change a property in one class, it will be reflected everywhere else. Check out this example of how we would modify the Config class to use the singleton.

The first thing you should notice is the static property $instance. This will hold the only instance of the class during run-time. The constructor has been made private, which means that trying to instantiate this class in the normal fashion will return an error. Instead, we are forcing users of this class to call the static method getInstance(). Why?

getInstance() is where the magic happens with the singleton pattern. If this is the first time the method has been called, then a new instance is created and stored in $instance. Henceforth, the same instance of the class is returned.

So what does this all mean? Let's go back to the original example.

As you can see, the method of instantiating Config has been replaced with the getInstance() static call. And this time, when class A changes the property $debug, it is realized in every other class.

Consequences

Using the singleton pattern saves a lot of server memory and cpu cycles because it does not have to be instantiated over and over (This can be dependent on the particular language you are using). It should also save you some strained muscles from having to prevent you from bending over backwards to pass these types of variables across your application.

The bad news is that the singleton still reeks of the same problems that global variables do. Dependencies are created and are hard to trace. Modularity suffers because of this. However, I think if used sparingly and with great care, the singleton pattern can benefit you greatly.

Other Opinions

I think it's worth mentioning that the Singleton comes under a lot of fire. Not so much for its usefulness but for other things. Not so much for how effective the singleton can be if used properly, but for other things. Personally, I think most are being nit-picky and just give developers something to argue over. Regardless, here are a few examples:

Edit: If you're abiding by the pattern's definition and use it in acceptable situations than I consider some of the arguments to be nit-picky :)

Get my RSS Feed!

Comments

Chris on (1.28.2009 7:07 pm) says

btw. you can just use http://paste.mootools.net/f48cd80eb

Shortest and cleanest singleton pattern in php to date. It eventually does not follow the rule that the class stores its instance as the static var belongs to the function, but that is pointless nitpicking.

 

Jani Hartikainen on (1.28.2009 8:32 pm) says

Nice intro to singleton - and you also did what many often forget - linked to some differing opinions about it.

While I sometimes use singletons as a replacement for globals, I kind of agree with what some say regarding it... It doesn't really solve any of the problems of a global variable, except that it's immutable. 

If you want to find a possible better alternative to singletons, I would suggest looking into dependency injection/inversion of control. Somewhat more complex than singletons, though.

 

Steven Van Poeck on (1.29.2009 1:28 pm) says

Since it's PHP5, it might be worth mentioning that you should also include a private function __clone() method.

 

PiccoloPrincipe on (2.2.2009 9:59 am) says

I appreciate linking to other opinions, but the intro doesn't make such sense..
"A global variable therefore has an unlimited potential for creating mutual dependencies, and adding mutual dependencies increases complexity."
That's the same for a singleton, there's no difference in writing:
Config::getInstance()->get('someFolderPath');
and:
$GLOBALS['config']->get('someFolderPath');

 

Tass Skoudros on (8.25.2009 10:35 am) says

You made good points, and I completely agree its easy to use the singleton pattern for the wrong reasons. I guess the same can be said for most of the patterns if used incorrectly. 

I advocate the use of the singleton pattern nonetheless because it can help to improve performance with of applications by limiting the creation of instances when interfacing with datasources.

If you're working within the MVC architecture it becomes useful to manage connections to data sources with the singleton pattern. As PHP develops multi threading it could be useful to manage thread pulls with the singleton pattern (similar to Java, Flex). 

With anything the best way to develop software is to ask yourself before you add another line of code if what you're adding can be done another way. As always DRY and KISS. 

Great article, I hope I have provided valuable information. 

Cheers
Tass Skoudros

 

Tass Skoudros on (8.25.2009 11:06 am) says

I realised I made some mistakes making my comment (your comment box is so small) thought I'd correct them and provide an example of what I would use the singleton pattern for. 
To fix my errors;
On line 6: performance with of applications
On line 11:useful to manage thread pulls pools with

Some code using a CakePHP datasource

Class xyz_source extends DataSource
{

function singleton(){		
self::$instance || self::$instance = new SoapClient($this->wsdl);
return self::$instance;
		
}

function add_widget($data){
try{

/* $this->key is setup in the constructor, values from your controller can be loaded. Any Sanitising can be done in the controller.*/

$this->key = $data;
return self::singleton()->AddWidget($this->key);

}catch (Exception $e){echo $e->getMessage();}

}

}

 
* Name
* Email (Will not be displayed)
Website