Friday, February 6, 2009

Design - Singleton Pattern

JVM is a virtual machine where you find threads, objects, classes, classloaders, garbage collector etc having their own living space in the machine. Of all these it is the threads which keeps the metabolism going. When all the threads are dead the virtual machine dies. During its lifetime these threads create, edit or act upon multiple objects. Objects hold data and defines the behavior. In certain instances we need specialized objects holding data which needs to be shared across the virtual machine. This requires us to maintain only one instance of the object which is shared across multiple threads in the jvm. This is defined by Singleton pattern. Below are my thoughts and understandings of this pattern.

The basic definition of this pattern is as below.
1. Make the object constructor private. This allows the control on object creation.
2. Define the static object reference to self to hold the instance of this object.
3. Define the static getter method to get a reference to the object.
There are many flavors of pattern implementation, which are as below.

A. A very simple way of implementing Singleton is as below. This works in both the situations of single and multi-threaded environment.
public class Singleton{
private static final Singleton instance = new Singleton();
//Other data attributes go here...
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
//Other methods go here...
}

The above method is simple and very effective, but this may not be desirable in few design situations. The above method does early initialization of the object while the below methods talk about the lazy initializations.

B. When more control is needed, like handling the situations when the initialization in the constructor throwing exception. Though exception may be handled in the constructor or a new exception can be thrown from constructor, we may want to return null value to the to the calling method rather than return this partially initialized instance.
//CASE: Single threaded environment:
public class Singleton{
private static Singleton instance = null;
//Other data attributes go here...
private Singleton(){}
public static Singleton getInstance(){
if(instance = null) instance = new Singleton();
return instance;
}
//Other methods go here...
}
//CASE: Multi threaded environment
public class Singleton{
private static Singleton instance = null;
//Other data attributes go here...
private Singleton(){}
private static synchronized Singleton createInstance(){
if(instance == null){
//Exception handling can be done here.
instance = new Singleton();
}
return instance;
}
public static Singleton getInstance(){
Singleton singleton = instance;
if(singleton = null){
singleton = createInstance();
}
return singleton;
}
//Other methods go here...
}

C. There is also the other reason why we may not do the early initialization. If we wish to extend from the Singleton class. Below style talks of this in the multi threaded environment.
//CASE: Parent:
public class Singleton{
protected static Singleton instance = null;
//Other data attributes go here...
protected Singleton(){}
private static synchronized Singleton createInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
public static Singleton getInstance(){
Singleton singleton = instance;
if(singleton = null){
singleton = createInstance();
}
return singleton;
}
//Other methods go here...
}
//CASE: Child
public class ChildSingleton extends Singleton{
//Other data attributes go here...
protected ChildSingleton(){}
private static synchronized Singleton createInstance(){
//Overriding the createInstance behaviour
if(instance == null){
instance = new ChildSingleton();
}
return instance;
}
//Other methods go here...
}

However be careful in the above method as the protected access specifier indicates that it can be accessed by the other classes in the same package as well, which gives a leak to create multiple instances.

D.One of the good approaches I have come across. This works well in all situations and is lazy initialization as well.
public class Singleton{
//Other data attributes go here...
private Singleton(){}

public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
//Other methods go here...

//Inner class
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
}

But beware that Singleton may not really be a single instance and there can be many leaks. There are some more good articles on this topic. Few of them are mentioned below.
http://en.wikipedia.org/wiki/Singleton_pattern
http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html

No comments:

Learning programming

    Programming is an interesting world where you apply your skills to build a software program that comes into life when it is run on a com...