Sunday, 30 May 2010

Example program for singleton design pattern

//PrinterDemo class has implemented Cloneable, Serializable ( Serialization of Objects)
package com.raj;

import java.io.Serializable;

public class PrinterDemo implements Cloneable,Serializable
{
//if your super class has implemented this method, it will be automatically visible
@Override
public Object clone() throws CloneNotSupportedException
{
return(super.clone());
}

}

//Printer.java
//Printer class implementing Singleton Design Pattern
package com.raj;

public class Printer extends PrinterDemo 
{
private static Printer p=null;
//1st time true, 2nd time-false, Used for Reflection API Proof
//and Multi-Thread double check
private static boolean isNew=true;
//private constructor
private Printer()
{
//to prevent Reflection API creating Multiple objects
if(isNew)
//this sleep is added to prove MultiThread can create multiple Objects if they are not synchronized
try
{
Thread.sleep(5000);
}
catch(Exception e)
{
}
isNew=false;
System.out.println("Printer()");
}//if
else
{
throw new InstantiationError("Cannot create Multiple Object");
}//end of else
 }//end of constructor
public void print(String data)
{
System.out.println("Printer.print()..printing:"+data);
}
public synchronized final static Printer getInstance()
{
if(p==null)
{
p=new Printer();
}//end of if
return(p);
}//end of getInstance()
/*
* if you want to use synchronized block
* public static final Printer getInstance()
* {
*  if(p==null)
*  {
*   synchronized(Printer.class)
*   {
*    p=new Printer();
*    }
*   }
*   return(p);
*   }//end of getInstance()
* * 
*/
//Any Cloning process, then it will return same old object
public Object clone() throws CloneNotSupportedException
{
//throw new CloneNotSupportedException();
return(p);
}
//Any Deserialization Process will give you the same Object
protected Object readResolve()
{
System.out.println("readResolve()");
return(p);
}
}

//TestClient.java
package com.raj;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

class MyThread implements Runnable
{
public void run()
{
System.out.println("MyThread.run():"+Thread.currentThread().getName());
Printer p=Printer.getInstance();
p.print("Print 1");
System.out.println("HashCode"+p.hashCode());
}
}
public class TestClient 
{
public static void main(String args[]) throws Exception
{
System.out.println("creating Printer class object Normally");
Printer p1=Printer.getInstance();
Printer p2=Printer.getInstance();
Printer p3=Printer.getInstance();
p1.print("Print 1");
p2.print("Print 1");
p3.print("Print 1");
System.out.println("HashCode");
System.out.println("p1 :"+p1.hashCode());
System.out.println("p2 :"+p2.hashCode());
System.out.println("p3 :"+p3.hashCode());
System.out.println("Trying cloning Object");
//Remove Printer.clone(), it will create different objects
Printer p4=Printer.getInstance();
Printer p5=Printer.getInstance();
Printer p6=Printer.getInstance();
p4.print("Print 4");
p5.print("Print 5");
p6.print("Print 6");
System.out.println("HashCode");
System.out.println("p4 :"+p4.hashCode());
System.out.println("p5 :"+p5.hashCode());
System.out.println("p6 :"+p6.hashCode());
//de-serialization of objects
System.out.println("creating singleton object using Serialization and Deserialization");
//Remove Printer.readResolve() and it will create multiple object upon Deserialization
//please refer to   Reading Data from a File using FileInputStream if you have any doubts about //filesInputstream
FileOutputStream fos=new FileOutputStream("d:/printer.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(p1);
oos.close();
System.out.println("Object is serialized");
System.out.println("Now Deserialzing");
FileInputStream fis=new FileInputStream("d/printer.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Printer p7=(Printer)ois.readObject();
ois.close();
ois=new ObjectInputStream(new FileInputStream("d:/printer.txt"));
   Printer p8=(Printer)ois.readObject();
   
   p7.print("Print 7");
   p8.print("Print 8");
   
   System.out.println("HasCode;");
   System.out.println("p7 :"+p4.hashCode());
   System.out.println("p8 :"+p5.hashCode());
   
   System.out.println("Creating printer class Object using Multple Threads");
   
   //remove synchronized modifier (keyword) from getInstance(), you will see 2 different object
   Thread th1=new Thread(new MyThread());
   th1.start();
   
   Thread th2=new Thread(new MyThread());
   th2.start();
       
   System.out.println("creating Printer class object using Reflectio API");
   //Remove boolean check logic from printer constructor and it will create create different objects
   Class c=Class.forName("Printer");
   Constructor conList[]=c.getDeclaredConstructors();
   conList[0].setAccessible(true);//makes the constructor accessible
   
   Constructor c1=conList[0];
   //will create 3 new objects
   Printer p9=(Printer)c1.newInstance();
   Printer p10=(Printer)c1.newInstance();
   Printer p11=(Printer)c1.newInstance();
   
   p9.print("Print 9");
   p10.print("Print 10");
   p11.print("Print 11");
   
   System.out.println("p9 :"+p9.hashCode());
   System.out.println("p10 :"+p10.hashCode());
   System.out.println("p11 :"+p11.hashCode());
   
}
}
/*
Output: (some bugs are there, to be fixed)

HashCode
p4 :9634993
p5 :9634993
p6 :9634993
creating singleton object using Serialization and Deserialization
Object is serialized
Now Deserialzing
Exception in thread "main" java.io.FileNotFoundException: d\printer.txt (The system cannot find the path specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at com.raj.TestClient.main(TestClient.java:63)


*/
Singleton Design pattern
Example applications for Singleton java class

No comments:

Post a Comment