Praveen Singh

How to achive singelton class or singleton pattern in java ?

A singleton is simply a class that is instantiated exactly once.

Before Java 1.5 their was two classical way to create singelton class

Way 1: Public field approach

public class SampleClass {

public static final SampleClass INSTANCE = new SampleClass();

private SampleClass() {

}

}

// Way 2: factory-method approach

public class SampleClass {

private static final SampleClass INSTANCE = new SampleClass();

private SampleClass() {

}

public static SampleClass getInstance() {

return INSTANCE;

}

}


The main advantage of the public field approach is that the declarations make it clear that the class is a singleton the public static field is final, so it will always contain the same object reference.

Ok………now you might think their could be performance advantage, well there is no longer any performance advantage to the public field approach, modern Java virtual machine (JVM) implementations are almost certain to inline the call to the static factory method.

Coming to 2nd, one advantage of the factory-method (getInastance method approch) approach is that it gives you the flexibility to change your mind about whether the class should be a singleton without canging its API. The factory method returns the sole instance but could easily be modified to return, say, a unique instance for each thread that invokes it.

But often neither of these advantages is relevant, and the final-field approach is simpler and more usable.


Disadvantage or extra work in this approch


Its all start when you do serializable…………hmmm……….check it out !

To make a singleton class that is implemented using either of the previous approaches serializable it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, you have to declare all instance fields transient and provide a readResolve () method

Now through the serializable tools, someone can write a singleton instance to disk, and then read it back up, effectively getting a new instance. Even though the constructor is private, the serializable tools have special access to create instances of a class regardless. Serialization has a special hook it uses - a private method on the class being instantiated called readResolve() - which is meant to supply a 'hook' for a class developer to ensure that they have a say in what object is returned by serialization. Oddly enough, readResolve() is not static, but is instead invoked on the new instance just created by the serialization.

So wer have to add readResolve method in both the way !

private Object readResolve() throws ObjectStreamException {

return INSTANCE;

}

And yes I miss out Reflection attack, I which we can access private method and create a instance by private constructor too!

Ok so this much extra work, don’t we have better solution ?

Way 3: Singelton class using enum, the Best way but least widely use !

enum BestSingeltonClass {

INSTANCE;

private String test;

public String getTest() {

return test;

}

public void setTest(String test) {

this.test = test;

}

public void doStuff(String stuff) {

System.out.println("Doing " + stuff);

}

}

public class Test {

public static void main(String[] args) {

BestSingeltonClass.INSTANCE.doStuff("chking out !");

BestSingeltonClass.INSTANCE.setTest("Praveen");

System.out.println(BestSingeltonClass.INSTANCE.getTest());

}

}


This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

No comments:

Post a Comment