Singleton Pattern:
Singleton pattern in java means there should only be a single instance(object) of the class across the application.
Implementation :
Singleton can be implemented in various ways, following program depicts Singleton implementation.
Comments are given for each type of singleton implementation.
There are certain issues which can break Singleton pact:
Singleton pattern in java means there should only be a single instance(object) of the class across the application.
Implementation :
Singleton can be implemented in various ways, following program depicts Singleton implementation.
Comments are given for each type of singleton implementation.
There are certain issues which can break Singleton pact:
- Using Reflection one can call the constructor and initialize an Object. - To prevent throw an exception inside constructor.
- Using Serialization - To prevent return same instance in readResolve().
- Using clone - To prevent throw error in clone().
import java.lang.reflect.Constructor;
/**
* @author vikky.agrawal
* @see http://stackoverflow.com/questions/20421920/what-are-the-different-ways-we
* -can-break-a-singleton-pattern-in-java
*/
public class Singleton {
// here volatile works with java 1.5 and above.
private volatile static Singleton single_instance;
private Singleton() {
// preventing reflection
if (single_instance != null) {
throw new IllegalStateException(
"Singleton instance already created.");
}
System.out.println("Singleton constructor running");
}
public static Singleton getSingleton() {
// double lock mechanism
if (single_instance == null) {
// if 1st thread is executing here then second thread might have checked
// above condition hence both threads may exist here.
synchronized (Singleton.class) {
// prevent multiple threads from creating 2 instances.(2 phase
// lock)
if (single_instance == null)
single_instance = new Singleton();
}
}
return single_instance;
}
// preventing de-serialization
protected Object readResolve() {
return getSingleton();
}
// preventing cloning
@Override
public Object clone() throws CloneNotSupportedException {
// return INSTANCE
throw new CloneNotSupportedException();
}
public static void main(String args[]) throws Exception {
// Breaking the singleton pact
Singleton s = Singleton.getSingleton();
Class<Singleton> clazz = Singleton.class;
Constructor<Singleton> cons = clazz.getDeclaredConstructor();
cons.setAccessible(true);
Singleton s2 = (Singleton) cons.newInstance();
System.out.println(s.hashCode());
System.out.println(s2.hashCode());
}
}
// using static class pattern
class BillPughSingleton {
@SuppressWarnings("unused")
private static final long serialVersionUID = 1L;
private BillPughSingleton() {
}
private static class LazyHolder {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return LazyHolder.INSTANCE;
}
protected Object readResolve() {
return getInstance();
}
}
// Using early instantiation -- static
class SingletonStatic {
private static SingletonStatic instance = new SingletonStatic();
private SingletonStatic() {
System.out.println("Singleton(): Initializing Instance");
}
public static SingletonStatic getInstance() {
return instance;
}
}
// Using Enum
enum SingletonEnum {
INSTANCE;
public void distributePresents() {
// elided
}
/** Demonstrate use of SantaClaus. */
public static void main(String... aArgs) {
SingletonEnum fatGuy = SingletonEnum.INSTANCE;
fatGuy.distributePresents();
}
}
No comments:
Post a Comment