A singleton is simply a class that is instantiated exactly once.
Making a class a
singleton can make it difficult to test its clients, as it’s
impossible to substitute a mock implementation for a singleton unless it
implements an interface that serves as its type.
1) // Singleton with public final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
The main
advantage of the public field approach is that the declarations make it clear
that the class is a singleton: the public static field is final, so it will
always contain the same object reference. There is no longer any performance
advantage to the public field approach.
a privileged
client can invoke the private constructor reflectively (Item 53)
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.
2) // Singleton with static factory
public class Elvis {
private static
final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() { ... }
}
One advantage
of the factory-method approach is that it gives you the flexibility to change
your mind about whether the class should be a singleton without changing its
API.
To make a
singleton class that is implemented using either of the previous approaches 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 (Item 77).
Otherwise, each time a serialized instance is deserialized, a new
instance will
be created, leading, in the case of our example, to spurious Elvis sightings. To prevent this, add this readResolve method to the Elvis
class:
// readResolve method to preserve singleton property
private Object readResolve() {
// Return the one true Elvis and let the garbage
collector
// take care of the Elvis impersonator.
return INSTANCE;
}
As of release
1.5, there is a third approach to implementing singletons. Simply make an enum
type with one element:
3) // Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
This approach
is functionally equivalent to the public field approach, except that it is more
concise, provides the serialization machinery for free, and provides an ironclad
guarantee against multiple instantiation, even in the face of sophisticated serialization
or reflection attacks. While this approach has yet to be widely adopted, a single-element
enum type is the best way to implement a singleton.
Reference: Effective Java 2nd Edition by Joshua Bloch