Saturday, September 3, 2011

How to make a class Singleton?

The Singleton class means whose only one instance can be created. To make the class Singleton, we should restrict the ways through which the objects can be created. The object can be created in the following ways -
  1. Using new operator
  2. Using newInstance() method  (by Dynamic loading of class).
  3. Through Serialization/Deserialization
  4. Through Cloning
To restrict the ways of object  creation, we should take care of the following points -
  1. The Constructer must be private so that static (using new operator) and dynamic (using newInstance() method) creation of object does not get supported.
  2. Static field as object of the Singleton class should be declared within that class. In getInstance() method, it should be checked whether the static object has been instantiated or not. If not, then instantiate and return it.
  3. The method getInstance() must be Static and Synchronized. Static, so it can be accessed through the class name. Synchronized, because it should be thread-safe.
  4. The class must implement the Externalizable interface and override the writeExternal() and readExternal() methods such that serialization/deserialization should not be supported.
  5. The class must override clone() method so that another object could not get created.
Here is an example -

import java.io.*;

//Implement Externalizable interface to avoid object creation through Deserialization.
public class SingletonExample implements Externalizable {
    //make a static object
    private static SingletonExample g_instance;

    //make the construct as provate to hide it from outer world.
    private SingletonExample() {
        //do nothing
    }

    //make this static method as synchronized for thread-safe model.
    public synchronized static SingletonExample getInstance() {
        if (g_instance == null)             
            g_instance = new SingletonExample();
        return g_instance;
    }
    
    //override method and throw exception to avoid serialization     
    public void writeExternal(ObjectOutput out) throws SerializationNotAllowedException {
        throw new SerializationNotAllowedException("Serialization is not supported.");
    }     

    //override method and throw exception to avoid deserialization
    public void readExternal(ObjectInput in) throws SerializationNotAllowedException {
        throw new SerializationNotAllowedException("Deserialization is not supported.");
    }         

    //override method to avoid object cloning
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Cloning not allowed");
    } 
}

//As the methods writeExternal and readExternal throws IOException, hence we have to extend to create our own Exception.
class SerializationNotAllowedException extends IOException {
    public SerializationNotAllowedException(String message) {
        super(message);
    }
}

1 comment: