Creational
Patterns
Singleton
Pattern
A singleton pattern suggests that the
implementing class does not want its
instance to be created more than once (or restrict number of instances), thus
making it restrictive constructor in order to avoid using ‘new’.
In general, the singleton class has:
1. Declares a member variable to store
the class instance.
Early
instance creation vs
lazy instance creation:
In case, the class instance is created
while loading the class through class loader, is known as early instantiation.
In java, while declaring a member variable at class level, it can be declared
as ‘static’ with initialized to the new instance of the owner class. This way,
the class instance will be available at the time of application is started and classes are loaded.
singlInstance = new SingletonClass();singlInstance = new SingletonClass();
private
SingletonClass() {}
In
this case, the ‘getInstance’ method, which needs to
return the class instance would simply be:
public static SingletonClass
getInstance(){
return singlInstance;
}
In
case of the lazy initialization, the class member variable is declared as null
and the actual class instance gets created when the ‘getInstance’
method invoked for the first time.
public static SingletonClass
singlInstance = null;
private SingletonClass()
{}
public static SingletonClass
getInstance(){
if (singlInstance == null) {
singlInstance = new SingletonClass();
}
retutn
singlInstance;
}
Making
Instance Creation Thread Safe:
To
make the singleton class instance creation thread safe, there are 2 possible
solutions:
<![if !supportLists]>1.
<![endif]>Create
the instance of the class at the application class loading itself. This will
make sure that the instance will be always available just when the application
classes are loaded.
public
static SingletonClass singlInstance
= new SingletonClass();
So
when any thread accesses the ‘getInstance’ of the
class, the instance created early, will be always available and it will be
returned, thus making no new creation of instance later.
<![if !supportLists]>2. <![endif]>While with the lazy load, an
instance created in ‘getInstance’ method will not be
by default thread safe. To make it thread safe,
<![if !supportLists]>a. <![endif]>Defining ‘getInstance’
method as synchronized
We
can make the ‘getInstance’ method as synchronized, to
make sure the first thread which gets the access, will make other threads wait.
This will make sure that the instance will be created for the first time and
other threads, once obtain the lock would use the same instance created in
first thread.
public static synchronized SingletonClass getInstance(){
if
(singlInstance == null) {
singlInstance = new SingletonClass();
}
retutn
singlInstance;
}
<![if !supportLists]>b.
<![endif]>Making
a synchronized block
The
problem with synchronized method, is, it becomes
overhead, once the first instance created. So every later call, which will only
be getting the earlier created instance, needs to go in synchronized call. It
is very much unnecessary and can be avoided using synchronized block in ‘getInstance’ method.
public static SingletonClass
getInstance(){
if
(singlInstance == null) {
synchronized (SingletonClass.class)
{
singlInstance
= new SingletonClass();
}
}
retutn
singlInstance;
}
The
above implementation would help in making sure that the synchronization will be
applied only when the instance is not created, implying, all the calls post
initialization, would go directly avoiding any cost of synchronization.
However,
there is still an issue in the above implementation. The issue is mainly due to
the fact that, if there are multiple threads trying to access ‘getInstance’ method simultaneously, when the instance is
not yet created. In this case, all these threads will go in synchronized way,
but, each one will end up in creating new instance.
<![if !supportLists]>
i. <![endif]>Avoiding
faulty implementation
To
avoid the fault, we need to make double check. The ‘double check’ would imply
that, even if threads go in synchronized block as the instance is not created,
but when they actually start the execution of the block, re-verify if the
instance is still not created and then create it.
public static SingletonClass
getInstance(){
if
(singlInstance == null) {
synchronized (SingletonClass.class)
{
if (singlInstance == null) {
singlInstance = new SingletonClass();
}
}
}
retutn
singlInstance;
}
Handle
Cloning on the Singleton class
Cloning
in java, allows by default shallow copy of an object. However, it is necessary
that to have the class implementing the ‘Clonable’ interface, if it needs to clone
in later stage.
In
the above example, even if the user tries to get the clone on the SingletonClass
instance, the java program will end up in throwing java.lang.CloneNotSupportedException.
In
order to support coning in singleton, would mean
allowing coning, without creating any new instance if already created.
In
this case, we will need to implement ‘Clonable’ interface for our Singleton
class.
public
class SingletonClass implements Cloneable
and also, override the clone() method
private Object Clone(){
return
SingletonInstance;
}
Avoid
allowing the Singleton class extensible
To make sure your singleton class will not be
extended and used explicitly, you can make it ‘final’ class. (Note: By making
the constructor ‘private’, would mean, the extensibility is also avoided.
However, it is a best practice to make a class final, if you know it should not
be extended)
Handle
Serialization on Singleton Class
Serialization in java will allow storing the
state of the object. The state can be saved in a file. The stored state can be
read using de-Serialization.
By
default, if anyone tries to serialize the singleton class object, it will throw
java.io.NotSerializableException
In
case if we need to make sure the singleton class state can be stored and used
in case it is crashed, we may want to use serialization.
To
allow the singleton class supports serialization, there are few changes will be
needed. These changes are important in order to keep the singleton class not
allow having multiple instances.
Below
are the changes we need to make:
<![if !supportLists]>·
<![endif]>Implement
the readObject method in your singleton class. And make
sure to return only the existing instance.
<![if !supportLists]>·
<![endif]>Here
is the sample implementation:
private void readObject (ObjectInputStream oInstream) throws IOException, ClassNotFoundException
{
oInstream.defaultReadObject();
if (SingletonInstance == null){
synchronized (SingletonClass.class) {
if (SingletonInstance == null){
SingletonInstance = this;
}
}
}
}
private Object readResolve()
throws ObjectStreamException {
return SingletonInstance;
}