Tuesday, November 06, 2007

Singleton Pattern

  • The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it
  • Singleton pattern assures that at any one time there is only one instance of the class
  • It is used where an instance can take consume large amount of resources
  • It is used to manage pools of resources, like connection or thread pools
  • A singleton class doesn't have a public constructor
  • An instance of the class can be obtained by calling a static method of the class which will return an unique instance
  • Java's implementation of the Singleton Pattern makes use of a private constructor, a static method combined with a static variable. Sample code:
    public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
    if(instance == null)
    instance = new Singleton();
    return instance;
    }
    }
  • The above code works fine - but only to some extent
  • When there are multiple threads accessing getInstance(), above code will no longer work as expected, it can give out multiple instances of the object
  • One simple solution is to make the method synchronized
    public static Synchronized Singleton getInstance()
  • But making a method synchronized affects performance by a factor of 100
  • Another option is to use eager instantiation rather than lazy instantiation, i.e., create the instance upfront, instead of creating it inside the getInstance() method. In this case JVM will make sure that the instance is created before any thread can access the static variable 'instance'.
    public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
    return instance;
    }
    }
  • Usage of double-checked locking will reduce the overhead of using synchronized keyword drastically. But it doesn't work Java 1.4 or earlier:
    public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
    if(instance == null) {
    synchronized(Singleton.class) {
    if(instance == null) {
    instance = new Singleton();
    }
    }
    }
    return instance;
    }
    }
  • A singleton class cannot be subclassed, since the constructor is private
  • If multiple class loaders are being used, as each ckass kiader defines a namespace, multiple instances of the Singleton class will get created


(Ref: Chapter 5 - One of a Kind Objects, Head First Design Pattern)

No comments: