Sunday, July 12, 2009

Many times we face situations in which we need to model an entity which can have only one Live instance at a time. Speaking in technical terms, we need to create a class which can be instantiated only once i.e. only one object can be created of that class during the scope of the entire application. Examples can be an instance of a Printer which can be used by many clients to print any document. But since we have only printer, so we must not allow the user/client to create more than one instance of the Printer class. Rather all of them must use the same instance in an synchronized manner.

A more common example could be a handle to the Database Connection Pool. We must have only 1 instance of the Pool Manager, which in turn can allocate database connections from the common pool of connections and can put them back after they are used. Having more than 1 instance of the Pool Manager can result in problems, which can be really difficult to debug.

Lets see how to make a Java Class that can be used as a Singleton

Method 1

Inside your class, keep a count of how many instances have been created so far in a static variable. Now, you can throw an Exception in your constructor, the moment a client tries to create more than one instance. Example code given below:

Method 2

Make your class’ constructor Private and keep another private instance variable which can call the constructor. Create a public getter function for the retrieving the singleton object as shown below:

One problem with this approach is that one can use Reflection API to invoke the private constructor and thus the whole concept of Singleton class is violated as shown below:

This can be overcome by throwing an exception in the MySingleton constructor when it is called more than once (as we have done in first Method)

Another Caveat

Can you think of any more way the above code can be broken? By breaking, I mean can you create two instances of the above class.

Hint: Serialization !!

Answer: If your class implements Serializable interface or inherits some class which implements this interface, then this code can be broken by first serializing the object (saving the state of the object to some file) and then de-serializing it (retrieving back the original state). If we do not override readResolve() method as shown below:

To the best of my knowledge, now I think there is no way you can create another object with all these checks implemented. Please feel free to comment & discuss this and point out any problems with above mentioned techniques.