Singleton Design Pattern:
Why?:
The intent of a singleton class is to ensure a class has
only one instance, and provide a global point of access to it.
How?
- Make
the class of the single instance object responsible for creation,
initialization, access, and enforcement.
- Declare
the instance as a private static data member.
- Provide a public static member function that encapsulates all initialization code, and provides access to the instance
There are various approaches to achieve singleton behavior:
Eager
initialization:- where an instance of a class is created much before it is
actually required, in other words the instance is created at the startup only
irrespective of whether any class requires it or not.
public class EagerSingleton{
private
static volatile EagerSingleton instance = new EagerSingleton();
//private
constructor
private
EagerSingleton(){
}
public
synchronized static EagerSingleton getInstance(){
if(null ==
instance){
instance = new EagerSingleton();
}
return
instance;
}
}
Lazy Initialization:
means delaying the creation of object untill its
first requested.
public final static LazySingleton{
private static volatile LazySingleton instance = null;
//Private constructor
private LazySingleton(){}
private LazySingleton getInstance(){
if(instance==null){
synchronized (LazySingleton.class){
instance = new LazySingleton();
}
}
return instance;
}
}
//There is a problem with this implementation, I am keeping
it open for the discussion.
//why do we use volatile with
instance variable?
The above method has some
drawbacks, suppose there are Two threads T1 & T2 starts simultaneously
and both comes to create instance and execute if(instance == null), at
this point of time they both will get instance to be null, they sequentially go
into the synchronized block and create the instance. so this way you will end
up with 2 instances of a singleton class :)
This can be solved by double
check locking technique, where we recheck the instance variable in synchronized
block.
public final static LazySingleton{
private
static volatile LazySingleton instance = null;
//Private
constructor
private
LazySingleton(){}
private
LazySingleton getInstance(){
if(instance==null){
synchronized (LazySingleton.class){
if(instance==null){
if(instance==null){
instance = new LazySingleton();
}
}
}
}
return instance;
}
}
Static Block Initialization:
As you now the static blocks are executed during the
class loading and even before a constructor is called, so using this feature we
can achieve singleton for our class.
Lets see how?
public class StaticBlockSingleton {
private static final StaticBlockSingleton instance;
static{
try{
instance
= new StaticBlockSingleton ();
}
Catch(Exception
e){
Sysout(“Unexpected
result!!!”);
}
}
private StaticBlockSingleton(){};
public static StaticBlockSingleton
getInstance(){
return
instance;
}
Above code has one drawback. Suppose there are 5
static fields in class and application code needs to access only 2 or 3, for
which instance creation is not required at all. So, if we use this static
initialization. we will have one instance created though we require it or not.
Adding readReslove():
So fare we have covered like, how to implement our singleton
class, various issues and their resolutions.
Now there is could be one more situation, where you need to
frequently serialize your singleton class. So while deSerialization, it creates
a new object of a class.. OOOPPPPPSSSS…
Now how to solve this issue?
Well its pretty simple, you just need to add readResolve
method in your implementation to override it to return the existing instance of
you class.
Something like:
protected Object readReslove(){
return
instance;
}
clone():
So far so good, but there could be one
more violation in singleton pattern.
If your class is
implementing clonable interface then there is a possibility that you end up
creating multiple objects of your singleton class.
To avoid this
situation, you just simply override the clone of Object in your implementation of
singleton to return the same instance or simply throw an exception from there
saying CloneNotSupported Exception.
Like:
protected Object
clone() throws CloneNotSupportedException
{
//you can return the existing
instance
return instance;
//or, you can throw an exception
from here
throw new
CloneNotSupportedException(“Cloning not allowed for singleton classes”);
volatile will pick up the latest value from main memory.it will not take values from thread memory.
ReplyDelete•The classes java.lang.System and java.sql.DriverManager
ReplyDelete