The Singleton Pattern ensures that a class only has one instance and provides a global point of access to it. There are four ways to implement a Singleton Pattern. First is the lazily created instance, then the synchonized instance, then the eagerly created instance, and finally, the double-checked locking style. The lazily created instance has problems with synchonization, but doesn't instantiate unless needed. The synchonized version is the same as the lazily version, but can take much longer to return an instance because of the requirement to synchonize every call. The eagerly created instance is not synchonized, but creates an instance even if not used. The double-checked locking version is safest and is synchonized, but only partially, so there is not much speed penalty.
Examples of the Singleton Design Pattern follows:
// lazily created instance
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
// the synchonized version
public class Singleton {
private static Singleton singleton;
private Singleton() {}
// synchonized adds a 100X penalty for this method
public static synchonized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
// eagerly created instance
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return singleton;
}
}
// double-checked locking way
public class Singleton {
private volatile static Singleton singleton;
private Singleton() { }
// synchonized moved inside for less speed penalty
public static Singleton getInstance() {
if (singleton == null) {
synchonized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}