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 |
- 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.
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.
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.
If a class(same name, same package) is loaded by 2 diferent classloaders they represents 2 different clasess in memory.
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().