The singleton design pattern's intent is succinctly described by the seminal work of Gamma et al. [Gamma 1995]:
Ensure a class only has one instance, and provide a global point of access to it.
Because there is only one Singleton instance, "any instance fields of a Singleton will occur only once per class, just like static fields. Singletons often control access to resources such as database connections or sockets" [Fox 2001]. Other applications of singletons involve maintaining performance statistics, system monitoring and logging, implementing printer spoolers, or even ensuring that only one audio file plays at a time. Classes that contain only static methods are good candidates for the Singleton pattern.
...
This design pattern is often implemented incorrectly. Refer to rule LCK10-J. Do not use incorrect forms Use a correct form of the double-checked locking idiom for more details on the correct use of the double-checked locking idiom.
...
This is known as the initialize-on-demand holder class idiom. Refer to rule LCK10-J. Do not use incorrect forms Use a correct form of the double-checked locking idiom for more information.
Noncompliant Code Example (Serializable)
...
"If a singleton contains a nontransient object reference field, the contents of this field will be deserialized before the singletonâs readResolve
method is run. This allows a carefully crafted stream to 'steal' a reference to the originally deserialized singleton at the time the contents of the object reference field are deserialized" [Bloch 2008].
Compliant Solution (Enumeration Types)
Stateful singleton classes must be nonserializable. As a precautionary measure, classes that are serializable must not save a reference to a singleton object in their nontransient or nonstatic instance variables. This prevents the singleton from being indirectly serialized.
Bloch [Bloch 2008] suggests the use of an enumeration type as a replacement for traditional implementations when serializable singletons are indispensable.
...
When the singleton class must indirectly implement the Cloneable
interface through inheritance, the object's clone()
method must be overridden with one that throws a CloneNotSupportedException
exception [Daconta 2003].
Code Block | ||
---|---|---|
| ||
class MySingleton implements Cloneable { private static MySingleton instance; private MySingleton() { // private constructor prevents instantiation by untrusted callers } // Lazy initialization public static synchronized MySingleton getInstance() { if (instance == null) { instance = new MySingleton(); } return instance; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } } |
...
This compliant solution demonstrates this technique. It prints a consistent hash code across all scopes. It uses the ObjectPreserver
class [Grand 2002] described in rule TSM02-J. Do not use background threads during class initialization.
...
Bibliography
Item 3. Enforce the singleton property with a private constructor or an enum type; and Item 77. For instance control, prefer enum types to | |
Item 15. Avoiding singleton pitfalls | |
9.10 Enforcing the Singleton Pattern | |
[Fox 2001] | |
Singleton | |
Chapter 5, Creational Patterns, Singleton | |
[JLS 2005] |
...