今天回头看了单例模式,以前从没用过枚举单例,学习了一下,Enum Singleton 是目前最优的单例模式,好处有三:
1. 枚举写法简单
下面这段代码就是声明枚举实例的通常做法,它可能还包含实例变量和实例方法,但是为了简单起见,我并没有使用这些东西,仅仅需要小心的是如果你正在使用实例方法,那么你需要确保线程安全(如果它影响到其他对象的状态的话)。默认枚举实例的创建是线程安全的,但是在枚举中的其他任何方法由程序员自己负责。
/**
* Singleton pattern example using Java Enumj
*/
public enum EasySingleton{
INSTANCE;
}
你可以通过EasySingleton.INSTANCE来访问,这比调用getInstance()方法简单多了。
2. 枚举自己处理序列化
传统单例存在的另外一个问题是一旦你实现了序列化接口,那么它们不再保持单例了,因为readObject()方法一直返回一个新的对象就像java的构造方法一样,你可以通过使用readResolve()方法来避免此事发生,看下面的例子:
//readResolve to prevent another instance of Singleton
private Object readResolve(){
return INSTANCE;
}
这样甚至还可以更复杂,如果你的单例类维持了其他对象的状态的话,因此你需要使他们成为transient的对象。但是枚举单例,JVM对序列化有保证。
3. 枚举实例创建是thread-safe
正如在第一条中所说的,因为创建枚举默认就是线程安全的,你不需要担心double checked locking。
总结:枚举单例有序列化和线程安全的保证,而且只要几行代码就能实现是单例最好的的实现方式.
下面是自己的例子
<span style="font-family:SimSun;font-size:14px;">package singleton;
/**
* 枚举单例
* @author Administrator
*
*/
public enum EnumSingleton {
INSTANCE;
/**
* 私有构造方法
*/
private EnumSingleton(){
System.out.println("-----构造方法");
}
/**
* 实现函数
* @param i
*/
public void say(int i){
System.out.println("i :" + i);
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
EnumSingleton.INSTANCE.say(1);
EnumSingleton.INSTANCE.say(2);
EnumSingleton.INSTANCE.say(3);
}
}
</span>
运行结果:
-----构造方法
i :1
i :2
i :3
只调用了一次构造方法