Singleton is one of the most common design patterns, but it has many implementation variants: lazy Instantiation, eager Instantiation, static holder idiom, and etc. Static holder idiom is my favorite.
package org.codeexample.jefferyyuan.javacode.singletons;
import java.io.Serializable;
public class SinletonVariants {}
/**
* When the singleton class is referenced, its instance would not be created,
* and also Java guarantees that the class initialization is atomic.
*
* So using the static holder idiom, we combine the benefit of lazy
* instantiation and no further synchronization after the instance is created,
*
* My favorite, always use this one.
*/
class SingletonHolderIdiom {
private SingletonHolderIdiom() {}
private static class SingletonHolder {
private static final SingletonHolderIdiom instance = new SingletonHolderIdiom();
}
public static SingletonHolderIdiom getInstance() {
return SingletonHolder.instance;
}
}
/**
* To maintain the singleton guarantee, you have to declare all instance fields
* transient and provide a readResolve method that directly return the static
* instance, also you must use eager instantiation.
*
* see Effective Java 2nd Edition: Item 3: Enforce the singleton property with a
* private constructor or an enum type
*/
class SerializableSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private static SerializableSingleton instance = new SerializableSingleton();
private SerializableSingleton() {}
public static SerializableSingleton getInstance() {
return instance;
}
// readResolve method to preserve singleton property
private Object readResolve() {
return instance;
}
}
/**
* This variant avoids the drawback of eager instantiation, as no resources are
* allocated before the instance is actually accessed, but further
* synchronization might seem unnecessary and expensive after the instance is
* already constructed.
*
*/
class SingletonLazyInstantiation {
private static SingletonLazyInstantiation instance;
private SingletonLazyInstantiation() {}
public static synchronized SingletonLazyInstantiation getInstance() {
if (instance == null) {
instance = new SingletonLazyInstantiation();
}
return instance;
}
}
/**
* This would initialize this singleton class eagerly, when the class is loaded
* at first time. Thus, it may happen that the singleton instance is constructed
* even if it is not accessed. This is a drawback, especially when the
* construction is complex and time/resource consuming. The good part of this
* variant is its simplicity.
*
*/
class SingletonEagerInstantiation {
private static SingletonEagerInstantiation instance = new SingletonEagerInstantiation();
private SingletonEagerInstantiation() {}
public static SingletonEagerInstantiation getInstance() {
return instance;
}
}