这是这个设计模式第十三篇了,本来不打算写单例模式的,因为感觉单例模式简单了,不过经过一番研究发现,其实单例并不简单。接下来就说一说单例模式。
一说实现单例模式的方式,有人说单例模式不就是构造函数私有化,构造静态方法,返回私有化实例吗?其实这里面也是有学问的,下面上一段代码,看看有什么问题:
class SingletonIdleMode{
//私有化构造函数
private SingletonIdleMode(){}
//需要返回的实例引用
private static SingletonIdleMode singleton;
//获取实例方法
public static SingletonIdleMode getInstance(){
if(singleton == null)
singleton = new SingletonIdleMode();
return singleton;
}
}
乍看之下似乎没有问题,但是如果这段代码在多线程的程序里跑一下就会发现,获取的实例不止一个。问题出在if语句判断这里,如果当一个线程A获知singleton 为空,将要生成实例时,突然有事歇了一会,此时另一个线程B也来到if判断处,判断single为空,它生成一个实例,这是线程A把事情办完后,继续之前的操作生成实例,这是内存里就有两个实例SingletonIdleMode了,单例模式也就不再单例,上述的单例模式称为懒汉的单例模式。
解决上面的问题的方法有两种,一种是下面的所说饿汉模式:
class SingletonHangerMode{
private static SingletonHangerMode singleton = new SingletonHangerMode();
public static SingletonHangerMode getIntance(){
return singleton;
}
}
看上去很简单,和懒汉模式没有太大差别,只是将生成对象简单化了,直接先生成对象,这样也就解决了多线程的问题。
还有一种看起来更简单的方式,使用枚举:
enum SingletonEnum{
INSTANCE;
}
看起来是不是更简单,调用的时候只需要使用 SingletonEnum.INSTANCE就可以返回SingletonEnum实例了,因为枚举类型是线程安全的,所以枚举类型实现单例模式是不是更简单呢?