Wednesday, January 18, 2012

Singleton Pattern - The Correct Usage

The singleton pattern is perhaps the most widely (mis)used pattern. Developers who program in object-oriented languages use the singleton pattern whenever they think of a service or manager class. I have seen a lot of projects use singletons even when the singleton class never encapsulates any private data that needs to be handled for multiple instantiations. Usage of the singleton pattern - with a private constructor and a getInstance() method - ensures that only a single instance of a class exists and all threads use the single instance. A database manager class that maintains a local data cache is an ideal candidate for a singleton, as we wouldn't want to maintain multiple local caches; the singleton cache should be loaded once and preserved in memory for faster access. Operations on this cache should also be thread-safe. If a class does not hold and control access to private data, then simple object instantiation makes perfect sense.

Another common mistake with the singleton pattern implementation is doing the object instantiation in the getInstance() method by making it thread-safe and having a check to see if the object is already instantiated. Given below is the implementation logic in Java. The method getInstance() is made thread-safe by using the synchronized keyword. This approach degrades the application performance as a lock is obtained on the object every time a thread calls the getInstance() method.


MySingleton mySingleton = null;


public synchronized MySingleton getInstance() {
  if (mySingleton == null) {
    mySingleton = new MySingleton();
  }
  return mySingleton
}


A better alternative is to instantiate the singleton object at the time of declaration. In this case, the ClassLoader instantiates the singleton when it comes across its reference, well before any thread is active in the application. Since the getInstance() is no longer synchronized, this offers better performance.



MySingleton mySingleton = new MySingleton();  // Object instantiated during declaration


// No need to synchronize method
public MySingleton getInstance() {
  return mySingleton
}


The concurrency-optimized implementation of the Singleton pattern is explained in many Java Concurrency books, but hopefully now you won't have to read the whole book to learn this neat trick.