概念
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有某个对象被创建;而且还提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
保证一个类只有一个实例:如果你创建了一个对象,同时过一会后决定再创建一个新对象,此时会获得之前已创建的对象,而不是一个新对象。注意:普通构造函数无法实现上述行为,因为构造函数的设计决定了它必须总是返回一个新对象
为该实例提供一个全局访问节点:和全局变量一样,单例模式也允许在程序的任何地方访问特定对象。但是它可以保护该实例不被其他代码覆盖。
优点
缺点
结构类图
创建方式
如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。
如果需要延迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒汉式。 最好使用饿汉式
实现
所有单例的实现都包含以下两个相同的步骤:
new
运算符。如果你的代码能够访问单例类, 那它就能调用单例类的静态方法。 无论何时调用该方法, 它总是会返回相同的对象。
一、懒汉式
synchronized
将整个 getInstance() 方法设为同步(synchronized)。不高效,因为任何时候只能有一个线程调用getInstance() 方法,而同步操作只需要在第一次创建单例实例对象时才需要。
public class Singleton{ private static Singleton instance; // 加 synchronized 保证只有一个线程进入方法 public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
双重检验锁模式DCL
同步块加锁
public class Singleton{ // 声明成 static volatile private static volatile Singleton instance; // 私有,使外界构造方法失效 private Singleton(){ } // 声明成 static public static Singleton getInstance(){ // 非空时直接返回 if(instance == null){ synchronized(Singleton.class){ // 防止生成多个实例 if(instance == null){ instance = new Singleton(); } } } return instance; } }
第一个if非空直接返回,减少synchronized浪费性能
第二个if防止生成多个实例
懒汉式 静态内部类
public class Singleton{ // 静态内部类只会被加载一次,故 instance 单例且线程安全 private static class SingletonHolder { private static final Singleton instance = new Singleton(); } // getInstance()方法调用时才加载静态内部类 public static final Singleton getInstance(){ return SingletonHolder.instance; } }
二、饿汉式
public class Singleton{ // 饿汉式 private static final Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } }
三、枚举
public class Singleton{ /** *枚举类型是线程安全的,并且只会装载一次 */ public enum SingletonEnum{ INSTANCE; private final Singleton instance; SingletonEnum(){ instance = new Singleton(); } private Singleton getInstance(){ return instance; } } public static Singleton getInstance(){ return SingletonEnum.INSTANCE.getInstance(); } }