Sunday, 15 July 2012

Java Singleton Pattern


What is Singleton?

Singleton is a design pattern. This designing style allows the programmer to create only one object of the class; even if more than one is created, it is not an error, but the code allows only one. In singleton class, there will be always only one object functioning, at a given time.

Advantages

This style is useful when only one object instantiation is enough to do with all the operations and also when the system operates more efficiently when one instance exists.

Disadvantages

If implemented unnecessarily, this pattern puts needless constraints in circumstances where actually one instance for the whole class is not needed and imposes more global environment in the code.

Implementation

The singleton object always access global data. The global values (state) must be persistent between all operations. The singleton object is created through a method call (not from directly accessing a constructor). The method returns the object, if no object already exists earlier. The method is coded in such a way if an object is created earlier, it returns the reference of the same object. This is completely transparent (unknown) to the programmer. Not to allow the programmer to create the object directly (not through method call), the constructor is declared private. Some developers declare it protected also as private does not allow the access to unit test operations.

The developer should be a little careful with singleton operations in multithreaded environment. If the code includes simultaneous processing activities, the method should be made mutually exclusive (by declaring something like synchronized). The code should take care of not to allow, the developer, accidental cloning of singleton object.

4 steps to implement in singleton creation


  • Make the constructor private not to be accessed directly
  • Create a method that returns a singleton object
  • Apply synchronization to the method to be thread-safe
  • Override clone() method for not allowing to clone the singleton object

Following program takes all the above 4 steps into consideration to create a singleton object. A Student class is taken to illustrate.


public class Student
{
  private int marks;                 // assigned with default 0
  private static Student std;        // assigned with default null

  private Student() 
  {     
     // some code if required
  }
  public static synchronized Student getMe()
  {
    if(std == null)
    {
      std = new Student();  
    }
    return std;
  }

  public Object clone() throws CloneNotSupportedException
  {
     throw new CloneNotSupportedException("Not allowed on this singleton object");
  }

  public static void main(String args[])
  {
      Student std1 = getMe();
      Student std2 = getMe();

      std1.marks = 50;
      std2.marks = 60;
      System.out.println("std1 marks when std2 changes: " + std1.marks);   // 60

      std1.marks = 70;
      System.out.println("std2 marks when std1 changes: " + std2.marks);    // 70

      System.out.println("\nstd1 hash code: " + std1.hashCode());
      System.out.println("std2 hash code: " + std2.hashCode());
  }
}




 private int marks;
     private static Student std;

In the Student class two global variables marks and std are declared of type int and Student. Reference variable std is made static simply for the reason to be accessed from the static main() method; else not required (of course, not suggestible also).

     private Student() 
     {     
       // some code if required
     }

Observe, the way of developing a singleton, declare the constructor private so that outside classes cannot create Student object directly and must go through a method call only to create. This is also another programming paradigm making "public methods and private variables".

     public static synchronized Student getMe()
     {
       if(std == null)
       {
         std = new Student();  
       }
       return std;
     }


getMe() method is declared public to allow the other classes to call the method freely and also static to have the facility of calling the method from main() without the help of an object.

First time when the method is called, as std is null, std is instantiated. Next time when called again the method, std is not again instantiated and instead the same std object, created earlier, is returned. It is checked every time in if condition. Moreover, the method is made synchronized to be thread-safe to work without any data inconsistency in multithreaded environment. For example, two different classes may call the getMe() method concurrently, these classes should be safe to get a singleton object.

     Student std1 = getMe();
     Student std2 = getMe();

Two objects std1 and std2 are obtained by calling getMe() method two times. Infact, they look two different objects; but only one as they refer the same object std. Let us prove this. Observe, when std1 changes its marks std2 is getting affected and when std2 changes std1 gets affected.

     System.out.println("\nstd1 hash code: " + std1.hashCode());
     System.out.println("std2 hash code: " + std2.hashCode());

As both std1 and std2 are same, their hashCode() method returned the same value. This is a good proof.

     public Object clone() throws CloneNotSupportedException
     {
       throw new CloneNotSupportedException("Not allowed");
     }


The clone() inherited from Object class is overridden with an exception message and this does not allow any class to clone the Student object.




No comments:

Post a Comment

There was an error in this gadget