Singleton
What
A creational pattern, which only creates one and only one instance of a class. If instantiating another object, and an object already exists, it will return the object already created.
This pattern involves a single class which is responsible for creating an object while making sure that only one object gets created.
When you use this pattern, you define an object that will exist across all application scope and that you can easily access from anywhere in the code at any time
Sometimes it is necessary that one and only one instance of a particular class exists in the entire Java Virtual Machine. This is achieved through the Singleton design pattern
The singleton class must provide a global access point to get the instance of the class.
Example
Example
Why use Singleton
If you have some resource that
(1) can only have a single instance, and
(2) you need to manage that single instance,
Examples
Logs
but it can be passed in as a dependency for each class
Database/connection pool
Properties
caching
A Singleton candidate must satisfy three requirements:
controls concurrent access to a shared resource.
access to the resource will be requested from multiple, disparate parts of the system.
there can be only one object.
If not all are satisfied, should redesign
A singleton should be used when managing access to a resource which is shared by the entire application, and it would be destructive to potentially have multiple instances of the same class. Making sure that access to shared resources thread safe is one very good example of where this kind of pattern can be vital.
Disadvantages of Singleton
Using synchronized, a synchronized block can be accessed one thread at a time, this might create a bottleneck for even getting the instance of the object.
Unit testing
One of the major requirements of unit testing is that each test should be independent of others. This can cause tests to pass when, really, it's because they were called in a particular order
They carry state around for the lifetime of the application
They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.
Breaks Single Responsibility Principle
a class should not know whether it is a singleton or not. So if you want to limit the ability to instantiate, use the factory or builder patterns, which encapsulates creation. There, you can limit the number of objects to one or whatever you wish for.
Singletons Provide Global State
Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.
Types
Lazy initialization
The Singleton pattern is implemented by creating a class with a method that creates a new instance of the object if one does not exist.
If an instance already exists, it simply returns a reference to that object.
To make sure that the object cannot be instantiated any other way, the constructor is made private.
Although a Singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or resources until needed.
works fine in case of the single-threaded environment but when it comes to multithreaded systems, it can cause issues if multiple threads are inside the if condition at the same time
Thread Safe
is to make the global access method synchronized, so that only one thread can execute this method at a time.
provides thread-safety but it reduces the performance because of the cost associated with the synchronized method, although we need it only for the first few threads who might create the separate instances
Lazy initialization with Double check locking
The above works absolutely fine in a single threaded environment and processes the result faster because of lazy initialization.
However the above code might create some abrupt behavior in the results in a multithreaded environment as in this situation multiple threads can possibly create multiple instance of the same SingletonExample class if they try to access the getSingletonInstance() method at the same time.
In the multithreading environment to prevent each thread to create another instance of singleton object and thus creating concurrency issue we will need to use locking mechanism.
This can be achieved by synchronized keyword. By using this synchronized keyword we prevent Thread2 or Thread3 to access the singleton instance while Thread1 is inside the method getSingletonInstance().
So this means that every time the getSingletonInstance() is called it gives us an additional overhead. To prevent this expensive operation we will use double checked locking so that the synchronization happens only during the first call and we limit this expensive operation to happen only once.
Eager initialization
If the program will always need an instance, or if the cost of creating the instance is not too large in terms of time/resources, the programmer can switch to eager initialization, which always creates an instance when the class is loaded into the JVM.
But in most of the scenarios, Singleton classes are created for resources such as File System, Database connections, etc. We should avoid the instantiation until unless client calls the getInstance method
Static block initialization
This is similar to the eager initialization.
The main advantage of using the static block here is that it supports the options for exception handling for the instantiation of the singleton class.
Using Enum
Enum has some distinct benefits in terms of thread-safety during instance creation, serialization guarantee by JVM and amazingly reduce amount of code which makes it perfect choice of using as Singleton class.
Protects against reflection
only limitation is that they are only eagerly instantiated.
Initialization-on-demand holder idiom (Bill Pugh)
This idiom derives its thread safety from the fact that operations that are part of class initialization, which is guaranteed by the JVM.
It derives its lazy initialization from the fact that the inner class is not loaded until some thread references one of its fields or methods. This provides the best of both options and guaranteed to be thread-safe by the JVM.
The trick is to use private nested class to hold Singleton instance.
Singleton class using an inner static helper class.
When the singleton class is loaded, SingletonHelper class is not loaded into memory and only when someone calls the getInstance method, this class gets loaded and creates the Singleton class instance
doesn’t require synchronization
Cloning
Cloning the object can still copy it and result into duplicate object.
The clone of the singleton object can be constructed using clone() method of the object.
Hence it is advisable to overload clone() method of Object class and throw CloneNotSupportedException exception.
Protecting against reflection
Reflection API is a powerful API in java which can be used to instantiate any class even the class has private constructors. This will break the singleton design pattern.
To prevent your singleton from Reflection API, just throw an IllegalStateException from private constructor if anybody tries to create a second instance
Protecting Singleton From Deserialization
We frequently serialize and de-serialize the objects in Java. You know that de-serialization always creates a new instance of the class. This may destroy your singleton pattern.
To protect the singleton from de-serialization, you have to implement readResolve() method in your singleton class. It is called when the object is de-serialized.
Singleton vs Static classes
The Singleton pattern has several advantages over static classes.
a singleton can extend classes and implement interfaces, while a static class cannot (it can extend classes, but it does not inherit their instance members)
A singleton can be initialized lazily or asynchronously while a static class is generally initialized when it is first loaded, leading to potential class loader issues.
singletons can be handled polymorphically without forcing their users to assume that there is only one instance.
When to use static classes
Prime example of this is java.lang.Math which is not Singleton, instead a class with all static methods.
If your Singleton is not maintaining any state, and just providing global access to methods, than consider using static class, as static methods are much faster than Singleton, because of static binding during compile time.
But remember its not advised to maintain state inside static class, especially in concurrent environment, where it could lead subtle race conditions when modified parallel by multiple threads without adequate synchronization
You can also choose to use static method, if you need to combine bunch of utility method together.
Anything else, which requires singles access to some resource, should use Singleton design pattern.
Links
Last updated