1 单例模式的实现场景
创建一个对象需要消耗过多的资源,如要访问IO和数据库等资源,为避免产生多个对象消耗过多资源,需要考虑使用单例模式。
2 实现单例模式的几个关键点
1)构造函数私有化
2)通过一个静态方法或枚举返回单例类对象
3)确保单例类的对象有且只有一个,特别是在多线程环境下
4)确保单例类的对象在反序列化时不会重新构建对象
反序列化操作提供了一个很特别的钩子函数,类中具有一个私有的、被实例化的方法readResolve(),这个方法可以让开发人员控制对象的反序列化。为防止这种情况,需加入如下方法:
private Object readResolve() throws ObjectStreamException
{
return sInstance;
}
也就是在readResolve()方法中将sInstance对象返回,而不是默认的重新生成一个新的对象。
3 单例模式实现的几种方式
懒汉式和DCL方式不建议使用,这里都不做介绍。
3.1 饿汉式
public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
}
public static Singleton getInstance()
{
return instance;
}
}
优点:简单。
缺点:第一次加载Singleton类时instance就被实例化,不管是否被使用,不是按需进行实例化。
3.2 静态内部类单例模式
public class Singleton
{
private Singleton()
{
}
public static Singleton getInstance()
{
return SingletonHolder.sInstance;
}
private static class SingletonHolder
{
private static final Singleton sInstance = new Singleton();
}
}
这是推荐使用的单例模式实现方式。
3.3 枚举单例
public enum SingletonEnum
{
INSTANCE;
public void doSomething()
{
........
}
}
只用SingletonEnum.INSTANCE即可获得所需实例,默认枚举实例的创建是线程安全的,并且在任何情况下它都是一个单例。不像以上方式,在反序列化时可以通过钩子函数readResolve()去创建新的实例。枚举不存在这个问题,反序列化也不会生成新的实例。