The Singleton is a design pattern that can be used when you want to guarantee that there is only one instance of a particular class. Technically it is quite a simple pattern, involving only one class. Usually it is implemented like this:
- Make the constructor private.
- Provide a class scope method to access the instance.
- Disable copying
Along with the fact that it is often the first (and sometimes the only) pattern you learn, this seaming simplicity makes it the most misunderstood and thus most misused pattern. Only when you look into the alternatives, the nature of the Singleton becomes apparent.
One such alternative is a class that only has class scope methods and attributes. Employing such an approach has the following characteristics:
- The class looks like a Utility class.
- The class does not handle inheritance well.
- Refactoring is complicated.
Utility classes
A utility class provides access to commonly used functions. These functions are usually provided as class scope methods. The average developer does not expect state information in a utility class, while an object usually has state information attached. Don't confuse the users of your class.
Inheritance
Consider the following PHP code
<?php
// Define the class
class Foo {
public static function configure() { /* Implementation is omitted */ }
public static function doSomething() { /* Implementation is omitted */ }
}
// Configure it
Foo::configure();
// Use the class
Foo::doSomething();
?>Now you want to implement a derived class, because you would like to have an alternative:
<?php
// Define the class
class Bar extends Foo {
public static function configure() { /* Implementation is omitted */ }
public static function doSomething() { /* Implementation is omitted */ }
}
?>How is that code to be used? Of course:
<?php
// Configure the class
Bar::configure();
// Use the class
Bar::doSomething();
?>You did not gain anything by deriving from Foo, All occurrences of Foo in your code have to be replaced with Bar, because calls to Foo::doThis() will still use the implementation that you just decided to refine in Bar.
This is where the singleton comes in handy
<?php
class Foo {
/**
* @return Foo The single instance of this class
*/
public static function getInstance() { /* Implementation is omitted */ }
public function configure() { /* Implementation is omitted */ }
public function doSomething() { /* Implementation is omitted */ }
}
// Configure it
$foo = Foo::getInstance();
$foo->configure();
// Use the object
Foo::getInstance()->doSomething();
?>Now you want to implement a derived class, because you would like to have an alternative:
<?php
// Define the class
class Bar extends Foo {
/**
* Retrieves the single instance and (if not done already) stores it in class Foo.
* @return Bar The single instance of this class
*/
public static function getInstance() { /* Implementation is omitted */ }
public function configure() { /* Implementation is omitted */ }
public function doSomething() { /* Implementation is omitted */ }
}
// Configure it
$bar = Bar::getInstance();
$bar->configure();
?>So, where is the difference to the static version? Well, obviously a class is configured only once. So the initial configuration is done in exactly one place in your application. In all other places, you can just stick with
<?php
// Use the object
Foo::getInstance()->doSomething();
?>If your implementation of Singleton does not allow inheritance, there is something seriously wrong.
Refactoring
Let's say you found out you need a second instance of Bar. Do this:
<?php
class Bar extends Foo {
public static function getInstance($config = 'default')
{
if ($config === 'default') {
/* Original implementation goes here */
} else {
/* Additions go here */
}
}
}
?>While you should seriously consider getting your instances by some other means, this is a way to quickly enable the class to produce multiple instances.
Post new comment