修改自http://blog.sina.com.cn/s/blog_44163be90100q0zd.html
实现Singleton有以下三种方法。
1、将公有静态成员做成final域:
public class Elvis {
public static final Elvis INSTANCE = newElvis();
private Elvis() { }
public void leaveTheBuilding() {
System.out.println("Whoa baby, I'moutta here!");
}
public static void main(String[] args) {
Elvis elvis = Elvis.INSTANCE;
elvis.leaveTheBuilding();
}
}
2、将公有成员做成静态工厂方法:
public class Elvis {
private static final Elvis INSTANCE = newElvis();
private Elvis() { }
public static Elvis getInstance() { returnINSTANCE; }
public void leaveTheBuilding() {
System.out.println("Whoa baby, I'moutta here!");
}
public static void main(String[] args) {
Elvis elvis = Elvis.getInstance();
elvis.leaveTheBuilding();
}
}
3、单元素枚举类型:
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() {
System.out.println("Whoa baby, I'moutta here!");
}
// This code would normally appear outsidethe class!
public static void main(String[] args) {
Elvis elvis = Elvis.INSTANCE;
elvis.leaveTheBuilding();
}
}
4、比较:
1)需要注意的是,将公有静态成员做成final域享有特权的客户端可以借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器。如果要抵御这种攻击,可以修改构造器,让它在被要求创建第二个实例的时候抛出异常。
2)将公有静态成员做成final域和将公有成员做成静态工厂方法时,为了使Singleton类变成可序列化的,仅仅在声明上加上“implements Serializable”是不够的。为了维护并保证Singleton,必须声明所有实例域都是瞬时的(transient),并提供一个readResolve方法。否则,每次反序列化一个序列化的实例时,都会创建一个新的实例。
3)单元素枚举类型更加简洁、无偿的提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击时;它已经成为实现Singleton的最佳方法。
说明:关于序列化readResolve方法可参考http://blog.csdn.net/huangbiao86/article/details/6896565