Singleton pattern is a design solution where an application wants to have one and only one instance of any class, in all possible scenarios without any exceptional condition
Before seeing Some of the techniques which are commonly used to make a class Singleton, first let's familiarize with some common steps that each of these techniques uses:
1.Make the constructor private-
Other classes can instantiate any object of the class by using the new keyword. Therefore default constructor of the class needs to be made private.The new keyword can then be used from within the class only.
Before seeing Some of the techniques which are commonly used to make a class Singleton, first let's familiarize with some common steps that each of these techniques uses:
1.Make the constructor private-
Other classes can instantiate any object of the class by using the new keyword. Therefore default constructor of the class needs to be made private.The new keyword can then be used from within the class only.
2. One method to get the instance- Though we've made the constructor private so that other classes can’t instantiate but we should have one method to get the only one instance.
In the above example, we have the method getInstance() which is providing the one and only one instance of the class. First it is checking if the object is instantiated or not(by checking if it is null or not). If it is not done yet then it creates a new instance. The instance is made static because only one class level instance variable will be there.
3. Make it Thread safe- This can be achieved either by:
1. Making getInstance() method synchronized
2. Using Synchronized block
In the above example, we have the method getInstance() which is providing the one and only one instance of the class. First it is checking if the object is instantiated or not(by checking if it is null or not). If it is not done yet then it creates a new instance. The instance is made static because only one class level instance variable will be there.
3. Make it Thread safe- This can be achieved either by:
1. Making getInstance() method synchronized
2. Using Synchronized block
this method has one drawback. Suppose there are two threads T1 and T2. Both comes to create instance and execute “instance==null”, now both threads have identified instance variable to null thus assume they must create an instance. They sequentially goes to synchronized block and create the instances. At the end, we have two instances in our application.
To solve this double-checked locking can be used.
Let's have a look at few commonly used techniques to Create Singleton Class
Let's have a look at few commonly used techniques to Create Singleton Class
Eager initialization
In his approach instance of a class is created much before it is actually required.lets see its code
Lazy initialization
Lazy initialization
In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. This is typically accomplished by maintaining a flag indicating whether the process has taken place.Lets see it in code
Static block initialization
We know static blocks are executed during the loading of class and even before the constructor is called. We can use this feature
Bill pugh solution
Bill pugh suggest to use static inner class.
Using Enum
We can still create instances of the class by cloning the class. So we have to override the clone() method of the Object class so that if any attempt is made to clone the class it will throw a CloneNotSupportedException.
Still we can create instances of the class by Serialization and de-serialization. So we need to override the readResolve() method also:
The complete code is:We should use “volatile” keyword with instance variable if we are using double checked locking otherwise we might see out of order write error scenario, where reference of instance is returned before actually the object is constructed i.e. JVM has only allocated the memory and constructor code is still not executed. In this case, our other thread, which refer to uninitialized object may throw null pointer exception and can even crash the whole application.
For example:
2.How Serialization and de- serialization can brake the code if readReolve() is not used?
De-serialization always creates a new instance. Lets understand using an example:
Our Singleton class without readResolve method
Now we
serialize this class and de-serialize it after making some changes
We can See that two objects got created, thus defeating our purpose of making class singleton
Thread A
may assign a memory space for instance
before it is finished constructing instance
. Thread B
will see that assignment and try to use it. This results in Thread B
failing because it is using a partially constructed version of instance
2.How Serialization and de- serialization can brake the code if readReolve() is not used?
De-serialization always creates a new instance. Lets understand using an example:
Our Singleton class without readResolve method
readResolve
is used for replacing the object read from the stream. So this is enforcing singletons; when an object is read, replace it with
the singleton instance. This ensures that nobody can create another
instance by serializing and deserializing the singleton.3. Why we need to override the clone() Method?
By default, the
clone()
method is marked as protected, but if our SingletonObject extends another class that does support cloning, it is possible to violate the design principles of the singleton. Examine the following code snippet, which clones a singleton object.Our Singleton class without clone method
No comments :
Post a Comment