Singleton Pattern
The Singleton Pattern ensures a class has only one instance and provides a global point of access to it.
Bates and Sierra — Head First Design Patterns
Class Diagram
/images/posts/design-patterns/singleton.jpg
Singleton
is name of the class but also the type of the unique instance
variable. The variable is static
so it belongs to the class. The method getInstance()
is static
so can be access using Singleton.getInstance()
.
Key Points
-
Private Constructor. The class cannot be instantiated.
- Core. The
Singleton
class- manages the single instance,
- prevent other class from creating their instances,
- provide a global access point to the instance,
- can have its own data and methods.
- Lazy Initialization. The instance is created only the first time the method
getInstance()
is invoked. When the class is loaded by the class loader the instance is not yet created. Beneficial in case of resource intensive objects such as database connection. - Multiple Class Loaders. Each class loader defines a namespace so the same class is loaded multiple times. A custom class loader could be define to address the issue.
-
No Subclassing. Due to the
private
constructor the class cannot be instantiated and subclassed. If the constructor will be changed to public, the parent and the subclasses will share the same instance variable. Astatic
variable means it belongs to the class. - Garbage Collector 1.2 A curious issue happens in its implementation because the GC collected the singleton without a global reference to them. The only reference to a singleton is the singleton itself.
Implementation
public class Singleton {
private static Singleton instance;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// other data and methods
}
Multi-Threaded Application
The Singleton
could be used in a multithreaded environment. Two threads could enter the getInstance()
method at the same time. Ensure that each thread waits its turn before entering the method.
Different implementations are feasible in order to address the issue.
Lazy Implementation
public class Singleton {
private static Singleton instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (instance == null) {
istance = new Singleton();
}
return instance;
}
// other data and methods
}
Note. Synchronizing the getInstance()
method creates an important overhead for the application, performance can decrease by a factor of 100.
Eager Implementation
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
// other data and methods
}
Note. The JVM will create an instance of Singleton when the class is loaded. Fine if the application always uses a Singleton instance.
Double-Checked Locking Implementation
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
// other data and methods
}
Note. Just the creation of the instance is synchronized
because the issue comes from a possible concurrent creation and avoid the reduction of the performance. Synchronization happens only the first time the issue has to be created. The volatile
keyword
Prior Java5 an out-of-order write may allow the reference to be returned before the object was created. The new
operator is not atomic.
Drawbacks
- Global state. Singletons introduce a global state into a program
- anyone can access to the reference variable provided by Singleton ignoring the scope;
- global state state are very difficult to test;
- singleton user and singleton class become coupled together so really difficult to test
- solution: pass the singleton as parameter in the client’s constructor so the singleton can be mocked
- factory class or the client could enforce the singularity eliminating the global state
- issue: violation of the Single Responsibility Principle, the class should take care about its own task and the singularity
- Dependencies. Singleton can be accessed anywhere thanks to the static method
getInstance()
, no need to pass the reference variable as parameter.- issues:
- the signatures of the methods do not show their dependency anymore, the method could pull a singleton “out of thin air” [4];
- becomes more difficult to use and test the code, the developer should have a look at the inner code.
- issues:
- Test-driven and Agile Development. Have small tests covering most of the code
- test must be run in any order
- two test could modify a shared resource that is the singleton
References
IBM - User Your Singletons Wisely [1] Portland Pattern Repository - Pages about singleton [2] Portland Pattern Repository - Singletons Are Evil [3] Google - Why Singletons Are Controversial [4] JavaWorld - Simply Singleton [5] Interview questions about singleton [6]