Java- Singleton Design Pattern in Java - JavaTechWorld

Saturday, 11 February 2017

Java- Singleton Design Pattern in Java

This is the continuation of my previous blog, Reflection, Serialization/Deserialization, clone, multi-threaded access all of them really help to create new instance and violate basis singleton concept of having one and only one instance.
in today blog we will fix all these issue.
  • Reflection -  we have singleton definition in which we have private constructor and public static getInstance() method and then we have test case which create two instance then we create instance using reflection in the below program. Reflection work in singleton because we have set the constructor as accessible and and invoke it. So we will go into constructor to fix this issue we are going to check in constructor if instance is already created or not if it is not null then we will throw exception.
Example-
//MySingleton.java
package singleton;

public Class MySingleton {

private static MySingleton instance=new MySingleton();

private MySingleton() {
if(instance!= null) {
throw new RuntimeException("Can't create object");
}
//proceed with object creation
System.out.println(“User can’t create object using new keyword”);
}
public static MySingleton getInstance() {
return instance;
}
}

//How to use Singleton class

Class TestClass {
public static void main(String[] args) throws Exception{
MySingleton ms=new MySingleton();    // Not allowed
MySingleton ms1=MySingleton.getInstance();
MySingleton ms2=MySingleton.getInstance();
print(“MySingleton”+ms1);
print(“MySingleton”+ms2);
//Reflection
Class cls=Class.forName(“singleton.MySingleton”);      //This way i am going to load a class
//Using this cls i am going to get default constructor.
Constructor<MySingleton> ctr=cls.getDeclaredConstructor();     // I got the default constructor now it is private i can’t invoke it, so i am going to use setAccessible api. By using this i am changing constructor to public constructor.

ctr.setAccessible(true);
MySingleton ms3=ctr.newInstance();
print(“MySingleton ms3”,ms3);
}
static void print(String name, MySingleton object) {
System.out.println(String.format(“Object : Hashcode”, name, object.hashcode()));
}
}


  • Serialization/Deserialization-  To fix this issue related to serialization/deserialzation in singleton class we have to implement read resolve method in singleton class when deserialization happens it is guarantee java will call read resolve method before deserializing the object.
Example-

package singleton;
public Class MySingleton implements Serializable {
private static MySingleton instance=new MySingleton();
private MySingleton() {
System.out.println(“User can’t create object using new keyword”);
}
public static MySingleton getInstance() {
return instance;
}
private Object readResolve() throws ObjectStreamException {
System.out.println("Inside Read Resolve method");
return instance;
}
}

//How to use Singleton class

Class TestClass {
public static void main(String[] args) {
MySingleton ms=new MySingleton(); // Not allowed
MySingleton ms1=MySingleton.getInstance();
MySingleton ms2=MySingleton.getInstance();
print(“MySingleton”+ms1);
print(“MySingleton”+ms2);

//Serialization example
ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream(“xyz.ser”));
oos.writeObject(ms1);
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(“xyz.ser”));
MySingleton ms3=(MySingleton)ois.readObject();
print(“MySingleton”+ms3);
}
static void print(String name, MySingleton object) {
System.out.println(String.format(“Object : Hashcode”, name, object.hashcode()));
}
}

  • Clone-  Singleton object can be duplicated using clone method  to prevent that the easiest way to prevent is throw an exception from a clone method and not allow cloning, we have to throw CloneNotSupportedException from clone api.
Example-


package singleton;

public Class MySingleton implements Cloneable {

private static MySingleton instance=new MySingleton();
private MySingleton() {
System.out.println(“User can’t create object using new keyword”);
}

@Override
protected object clone() throws CloneNotSupportedException {
return super.clone();
}

public static MySingleton getInstance() {
return instance;
}
}
//How to use Singleton class

Class TestClass {
public static void main(String[] args) {
MySingleton ms=new MySingleton(); // Not allowed
MySingleton ms1=MySingleton.getInstance();
MySingleton ms2=MySingleton.getInstance();
print(“MySingleton”+ms1);
print(“MySingleton”+ms2);

//Cloneable example

MySingleton ms3=(MySingleton) ms2.clone();
print(“MySingleton”,ms3);
}
static void print(String name, MySingleton object) {
System.out.println(String.format(“Object : Hashcode”, name, object.hashcode()));
}
}
  • Multi-threaded- In our previous blog on singleton multi-threaded example multiple thread is able to create two instances. To fix this issue we have to implement double locking mechanism in this mechanism if one thread i accessing getInstance() method other thread is not able to access getInstance() method so we have used synchronized block. Suppose one more thing we have to notice one thread enters in getInstance() method and it saw instance is null then it tries to lock in singleton class by the time it got lock it is possible that some another thread might initialize your instance so it is very good approach to check instance is null or not even after getting a lock this is called double locking mechanism.
Example-


package singleton;

public Class MySingleton {

//private static MySingleton instance=new MySingleton();  //eagerly created instance.
private static MySingleton instance=null;
private MySingleton() {
System.out.println(“User can’t create object using new keyword”);
}
public static MySingleton getInstance() {

//Double check locking mechanism
if(instance==null) {
synchronized(Singleton.class) {
if(instance==null) {                         
instance=new MySingleton();
}
}
return instance;
}
}

//How to use Singleton class

Class TestClass {
public static void main(String[] args) {
MySingleton ms=new MySingleton(); // Not allowed
MySingleton ms1=MySingleton.getInstance();
MySingleton ms2=MySingleton.getInstance();
print(“MySingleton”+ms1);
print(“MySingleton”+ms2);
MySingleton ms3=MySingleton.getInstance();
print(“MySingleton”,ms3);
}
static void print(String name, MySingleton object) {
System.out.println(String.format(“Object : Hashcode”, name, object.hashcode()));
}
}

© 2014 JavaTechWorld. Designed by Bloggertheme9
Powered by Blogger.