目的
保证一个类仅有一个实例,并提供一个它的全局访问点。
动机
对于一些类而言,保证单一实例是必须的。例如拍电影的导演只有一个,系统中只有一个文件系统等。
实现Singleton的方法,可以让类保存自己的唯一实例,这个类保证其他类无法创建自己的对象,并向其他类提供获取自己所保存的唯一实例的方法。
适用性
- 当类只能有一个实例,而且客户端可以从一个中公开访问点访问它时。
- 当这个唯一实例应该是通过子类化可拓展的,并且客户无需更改代码就能使用这个拓展实例。
参与者
Singleton
- 定义一个Instance,允许客户访问其唯一实例。
- 可能负责创建其唯一实例。
效果
-
对唯一实例的受控访问
-
允许对操作和表示精化
实现
-
保证唯一实例
-
创建Singleton的子类
代码实例
静态常量饿汉式
class Singleton{
private final static Singleton instance=new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
特点:内存浪费,但线程安全,可用
静态代码块饿汉式
class Singleton{
private Singleton instance;
static{
instance=new Singleton();
}
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
特点:内存浪费,但线程安全,可用
懒汉式(原始版)
class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
//此处不安全
instance = new Singleton();
}
return instance;
}
}
特点:线程不安全,多线程不能使用
懒汉式(加锁)
class Singleton{
private static Singleton instance;
private Singleton(){
}
public static synchronized Singleton getInstance(){
synchronized(Singleton.class){
if(instance == null){
instance=new Singleton();
}
}
return instance;
}
}
特点:线程安全,无法并行,效率过低,不推荐
懒汉式(双重检查)
class Singleton{
private static volatile Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance=new Singleton();
}
}
}
return instance;
}
}
特点:线程安全,效率较高,懒汉式加载
静态内部类式
class Singleton{
private Singleton(){
}
private static class SingletonInstance{
private static final Singleton INSTANCE=new Singleton();
}
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
机理:静态内部类不随外部类加载而加载进内存。当静态内部类的静态变量和静态方法被调用时加载。(实现了懒汉式的效果)。
特点:线程安全,效率较高,懒汉式加载
枚举式
enum Singleton{
INSTANCE;
public void sayOK(){
System.out.println("ok~");
}
}
public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
singleton.sayOK();
}
}
机理:利用jvm保证线程安全和单例问题。
特点:简单,线程安全,防止反序列化重新创建对象(推荐)