Saturday 26 April 2008

(Synchronized) Singleton design pattern in Java

Singleton falls into the group of simple design patterns. Singleton is a class that has one and only instance in an application. As singletons are usually realized pools (connection, thread, …), cash memories or drivers.

Implementing singleton is quite simple task. The following steps have to be done:
  • declare constructor as private to ensure that no instance of the class can be created
  • implement public static method that returns the only instance of the class
Demonstration of the simple singleton follows:
public final class SimpleSingleton {

private static final SimpleSingleton theInstance = new SimpleSingleton();

private String textAttribute;

private SimpleSingleton() {
textAttribute = "Some text";
}

public static SimpleSingleton getInstance() {
return theInstance;
}

public String getText() {
return textAttribute;
}

}

Because the private constructor, no descendant of the class can be made, so it’s useful practice to declare the singleton class as final to indicate that.

In the example above you can see that instance of the singleton is initialized in the same moment when the class is initialized. If the initialization of the singleton is quite timely-consuming task or it’s not even known whether the singleton would be used then it’s useful to put the initialization off to the first moment when the singleton is needed. Demonstration follows:
public final class LazyInitializationSingleThreaded {

private static LazyInitializationSingleThreaded theInstance;

private LazyInitializationSingleThreaded() {
}

public LazyInitializationSingleThreaded getInstance() {
if (theInstance == null) {
// the dangerous line follows
theInstance = new LazyInitializationSingleThreaded();
}
return theInstance;
}

}

The above example can be safely used only in single threaded application. Because there is no synchronization of the code where the singleton is initialized, it can easily happen that two or more threads would enter the dangerous line. One solution is to synchronize whole method getInstance(), but then the synchronization check would be done whenever the method is called so that the performance would be quite low. The right solution is to synchronize only section where the instance is being initialized. Demonstration follows:
public final class LazyInitializationMultiThreaded {

private volatile static LazyInitializationMultiThreaded theInstance;

private LazyInitializationMultiThreaded() {
}

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

}

Keep in mind that singletons should not be serialized, because by de-serialization you get another instance of the singleton.

The last and more complicated case is when the singleton is defined as abstract class with descendants and the singleton while being initialized chooses the right descendant. This is useful when you need to have more singletons of the single type with different behavior. Demonstration follows:
public abstract class SingletonInheritance {

private static class CheerfulSingleton extends SingletonInheritance {};
private static class SadSingleton extends SingletonInheritance {};
private static class DefaultSingleton extends SingletonInheritance {};

private static SingletonInheritance theInstance;

public static SingletonInheritance getInstance() {
if (theInstance == null) {
synchronized (SingletonInheritance.class) {
if (theInstance == null) {
String mood = System.getenv("MOOD");
if (mood == null) {
mood = "";
}
theInstance = chooseInstance(mood);
}
}
}
return theInstance;
}

private static SingletonInheritance chooseInstance(String mood) {
if (mood.equalsIgnoreCase( "CHEERFUL" ))
return new CheerfulSingleton();
else if (mood.equalsIgnoreCase( "SAD" ))
return new SadSingleton();
else
return new DefaultSingleton();
}

private SingletonInheritance() {
}

}