Pages

April 24, 2014

Design Patterns - Singleton Pattern

Motivation

  • It's  important  for  some  classes  to  have  exactly  one  instance.  Although  there  can be many printers in a system, there should be only one printer spooler. There should  be  only  one  file  system  and  one  window  manager.  A  digital  filter  will  have one  A/D  converter.  An  accounting  system  will  be  dedicated  to  serving  one  company. (Ref-1)
  • There are many objects we only need one of: thread and connection pools, caches, dialog boxes, object that handles preferences and registry settings, object used for logging, and objects that acts as device drivers to devices like printers and graphic cards. In fact for many of these types of objects, if we were instantiate more than one we'd run into all sorts of problems like incorrect program behavior, overuse of resources and inconsistent result. (Ref-3)
  • Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to themselves.  (Ref-4)

Intent

  • Ensure a class only has one instance, and provides global point of access to it.  (Ref-2)


Structure

singleton-pattern-uml-class-diagram
Singleton Pattern UML Class Diagram


  • The instance class variable holds our one and only one instance of singleton.
  • The getInstance() method is static, which means it's a class method, so you can conveniently access this method from anywhere in your code using Singleton.getInstance(). That's as easy as accessing a global variable, but we get benefits like lazy instantiation from Singleton.
  • Our constructor is declared private only Singleton can instantiate this class.
  • Singleton is a normal class, it has other useful methods and instance variables. 

Implementation in Java

public class Singleton {
  private static Singleton instance;

  public static synchronized Singleton getInstance () {
    if (Singleton.instance == null) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }

  private Singleton () {
  }

  public void doSomething () {
  }
}


As you can see above code that getInstance() method ensures that only one instance of the class is created. The constructor should not be accessible from the outside of the class to ensure the only way of instantiating the class would be only through the getInstance method.


Improve Multithreading


The standard implementation shown in the above code is a thread safe implementation, but it's not the best thread-safe implementation because synchronization is very expensive when we are talking about the performance. There are  a few options to improve implementation.
  • Move to an eagerly created instance rather than a lazily created one, code turns into below.
 public class Singleton {
  private static Singleton INSTANCE = new Singleton();

  public static Singleton getInstance () {
    return Singleton.INSTANCE;
  }

  private Singleton () {
  }

  public void doSomething () {
  }
} 
  • Use "double-checked locking" to reduce the use of synchronization in getInstance(). Unfortunately double-checked locking doesn't work Java 1.4 or earlier.
 public class Singleton {
  private static volatile Singleton INSTANCE = new Singleton();

  public static Singleton getInstance () {
    if (Singleton.INSTANCE == null) {
      synchronized (Singleton.class) {
        if (Singleton.INSTANCE == null) {
          Singleton.INSTANCE = new Singleton();
        }
      }
    }
    return Singleton.INSTANCE;
  }

  private Singleton () {
  }

  public void doSomething () {
  }
}
  • A single-element enum type is the best way to implement a singleton. Enums comes into with Java 1.5.
public enum Singleton {
  INSTANCE;

  public void doSomething () {
  }
}


Warnings & Measures


To make a singleton class serializable, it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, you have to declare all instance fields transient and provide a readResolve method . Otherwise, each time a serialized instance is deserialized, a new instance will be created.

 // readResolve method to preserve singleton property
private Object readResolve() {
    return INSTANCE;
}

If a class(same name, same package) is loaded by 2 diferent classloaders they represents 2 different clasess in memory. 

The lack of a public or protected constructor guarantees a “monoelvistic” universe: exactly one Singleton instance will exist once the Singleton class is initialized—no more, no less. Nothing that a client does can change this, with one caveat: a privileged client can invoke the private constructor reflectively with the aid of the AccessibleObject.setAccessible method. If you need to defend against this attack, modify the constructor to make it throw an exception if it’s asked to create a second instance. (Ref-2)


Usages

Configuration classes, logger classes, in share mode(multithreading) resource accessing manager classes are implemented using the Singleton Pattern.


Related Patterns

Many  patterns  can  be  implemented  using  the  Singleton  pattern like  Abstract  Factory, Builder and Prototype.


JDK Implementations 

  • Java.lang.Runtime with getRuntime() method.
  • Java.awt.Toolkit with getDefaultToolkit().
  • Java.awt.Desktop with  getDesktop().

References

  1. Design Patterns: Elements of Reusable Object Oriented Software
  2. Efective Java - Joshua Bloch
  3. Head First Design Patterns
  4. OO Design