欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Singleton pattern

程序员文章站 2024-03-20 20:18:22
...
Singleton pattern's best practice,see below:
[url]http://a123159521.iteye.com/blog/689087
[/url]

Singleton with public final field



public class Elvis{
public satic final Elvis instance = null;
private Elvis(){}
public static Elvis getInstance(){
if (instance == null) {
instance = new Singleton1();
}
}
public void leave(){...}
}


this personal construction is called for once that instance
the public static final field Elvis.INSTANCE.

Singleton with static factory


public class Elvis{
private static final Elvis INSTANCE = new Elvis()
private Elvis(){...}
public static Elvis getInstance(){ return INSTANCE;}
public void leave(){...}
}


as Serializable, the Singleton Object can't be easily add "implements Serializable", we shouled be declare all fields in transient, and provider readResolve method, or every time serializable will be create new instance.


public class Elvis{
private Object readResolve(){
return INSTANCE;
}
}


since jdk 1.5, you can use single enum type.


public enum Elvis{
INSTANCE;
public void leave(){...}
}



that's cool, and this will be provider serializable for free.
and this is the best singleton practice.

there is a risk in above two implements except enum.

first: with multiple thread, the second is ok, cause is it is instance after class loader, but the first one has a problem.
should be change below:


public static Singleton1 getInstance() {
if (instance == null) {
synchronized (Singleton1.class) {
if (instance == null) {
instance = new Singleton1();
}
}
}
return instance;
}


you can call getInstance() return Object, if the Object is the same,and there hashcode must be same.

you may be think this is singleton well, there is an other bug.
there is a special client can call setAccessible(true) to reflect the private construct, so there will be exist two singleton object.


public static void main(String[] args) throws Exception {
Class<Singleton2> clazz = Singleton2.class;
Constructor<?>[] cons = clazz.getDeclaredConstructors();
Constructor<?> con = cons[0];
con.setAccessible(true);
Singleton2 s1 = (Singleton2) con.newInstance(null);
Singleton2 s2 = Singleton2.getInstance();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
}


modified as below:


public class Singleton2 {

private static final Singleton2 INSTANCE = new Singleton2();

private Singleton2() {
if(INSTANCE != null){
throw new UnsupportedOperationException("Singleton Object");
}
}

public static Singleton2 getInstance() {
return INSTANCE;
}

}


that's well, in same classLoader, there must be singleton.
as multipe ClassLoader, there should be exist difference Objects.
this is needn't to sync, because this is skip the singleton's area