Design patterns are reusable solutions to common software engineering problems. They are best-practice in software design. It is not easy to apply them, and it often happens that pattern misuse may lead to bigger problems, a good design supported by patterns will last and give you less headaches. Examples in PHP and Java are given.
Singleton is a creational pattern (creational patterns deal with object creation mechanisms) which restricts instantiation of a class to one (and only one) object. We’ll discuss it in 3 chapters:
Problem
What use is of that, you may ask? Many objects need just one instance like thread pools, logging objects, database connections, caches… Quite some problems might occur if more than one instance would be made. Could end up deadlocking resources or making resources invisible to each other.
The old way would be using global variables. We all know (if we somehow ended up looking for design patterns) that global variables are not a good solution to any problem. That way the responsibility of maintaining variables is on the programmer (this is a very bad idea also!).
Solution
A solution that will always give us the same instance of a class, and won’t let anyone create more is needed. The logical solution would be a single point for getting an instance, while disabling all other possibilities. We can make the constructor and the clone method invisible by making them private. Now the only way of making an instance is by calling the constructor from within the class and that isn’t possible unless…
Static variables and methods to the rescue! Recall that static methods act at class level rather than at instance level. No object is needed to call a static method. This gives a nice way to instantiate, because through the static method a private constructor can be called.
The instance created should be kept somewhere, so it can be returned on consecutive calls but it must persist during the whole program run-time. Recall that static variables are allocated at compile-time, or in other words, their lifetime extends across the whole run-time of the program.
Put together, we can use a static method and a static variable to construct a single instance and keep it over all calls.
Let’s see the class diagram for the given description:
and clarify it even more with code in Java.
public class Singleton { // Hold an instance of the class private static Singleton instance; // A private constructor prevents direct creation of object private Singleton() {} // The singleton method public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
if you somehow inherited the clone() method, you can disable it like this
// You can not private clone(), so make it throw an exception public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
The only way to make an instance of Singleton is by calling the getInstance() method as
Singleton singleton = Singleton.getInstance();
Here’s the same code in PHP
class Singleton { // Hold an instance of the class private static $instance; // Disable clone function private function __clone() {} // A private constructor; prevents direct creation of object private function __construct() {} // The singleton method public static function getInstance() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } }
and the call
$singleton = Singleton::getInstance();
Since PHP is weakly typed and Java is strongly typed there is one major difference in the way of using the classes:
- The PHP class can be inherited and only needs to have the constructor rewrited. Of course, you can add class specific methods and variables.
- The Java class isn’t really good for inheriting. If you want to use a Java Singleton for multiple classes there are some examples using generics, but I don’t recommend them. The best way is to write a class for each Singleton you need.
We can upgrade the Java class a bit, so if it is a database connection class, and you want to hold a single connection to a MySQL, Oracle, MSSQL database, you can add a static HashMap and depending on the connection type, save each instance to the corresponding slot.
It might be the simplest pattern in terms of diagram and implementation, but it is very useful nevertheless.
Pitfalls and solutions
Although simple it has one pitfall in multithreading languages. This can’t happen in PHP because it doesn’t natively support multithreading.
Let’s imagine that we have 2 threads that ran getInstance(). The threads may overlap in this way:
Thread 1 | Thread 2 |
---|---|
Singleton singleton = Singleton.getInstance(); | |
Singleton singleton = Singleton.getInstance(); | |
if (instance != null) { | |
if (instance != null) { | |
instance = new Singleton(); } return instance; | |
instance = new Singleton(); } return instance; |
Yes, the chance for this to occur is very low, but still, compared to the time used to overcome it, can make quite a mess.
This may happen because we use lazy instantiation. That means an object is created on the first getInstance() call. There are 3 solutions to this problem. Only changes to the class are given.
Make the method synchronized
// The singleton method public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
This is a straightforward solution, but if this portion of code is often used, it may cause overheads, and decrease performance. It would be good if we could only synchronize the first time, and after just return the instance.
Eagerly created instance instead of lazily
// Hold an instance of the class private static Singleton instance = new Singleton(); // The singleton method public static synchronized Singleton getInstance() { return instance; }
Create the instance earlier, and rely on the JVM that the object is created before any thread accesses the method.
Use “double-checked locking”
// Hold an instance of the class private volatile static Singleton instance; // The singleton method public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }
Check if there is an instance and only if there isn’t synchronize. The volatile keyword ensures the order of reading and writing the variable among multiple threads.
Singleton pattern, over and out..
I liked your article is an interesting technology
thanks to google I found you
Useful details! I have been looking for anything like this for a while these days. Many thanks!
I couldn’t refrain from commenting. Well written!