Java单例模式

单例模式:一个类只允许产生一个实例
单例模式分为饿汉式单例、懒汉式单例、Double CheckLock实现单例、静态内部类单例、和枚举实现单例。
单例模式的适用场景

  1. 需要生成唯一序列的环境;
  2. 需要频繁实例化然后销毁的对象;
  3. 创建对象是耗时过多或者耗资源过多,但又经常用到的对象;
  4. 方便资源相互通信的环境;

目的:整个程序应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例

1、饿汉式单例
特点:线程安全,调用效率高,不能延时加载
类一加载的时候,就会把自身对象创建起来(直接把对象定义出来)
步骤:
a. 私有化构造器(外界不能构造对象)
Java单例模式
b. 实例化自身的类(静态,final可写可不写,加上final保险一些),定义一个私有的静态变量来放自身的实例
Java单例模式
c. 创建静态工厂方法,让外部可以获取实例,返回自身实例
Java单例模式
2、懒汉式单例
特点:线程安全,调用效率不高,能延时加载(使用的时候再加载)
先定义,但不同时创建对象
步骤:
a. 私有化构造器
b. 类初始化时,不创建对象,用的时候再创建(延时加载)
Java单例模式
c. 方法同步,调用效率低;创建静态工厂方法,让外部可以获取实例
Java单例模式

3、Double CheckLock实现单例:双重锁判断机制(由于JVM底层模型原因,偶尔会出问题,不建议使用),是在懒汉式单例上发展而来
简单了解一下:
Java单例模式

4、静态内部类单例:内部类是定义在类里面的类
特点:线程安全,调用效率高,可以延时加载
步骤:
a. 私有化构造器
b. 在外部类里面写一个静态内部类
Java单例模式
c. 创建静态工厂方法
Java单例模式
5、枚举实现单例
特点:线程安全,调用效率高,不能延时加载
Java虚拟机会在底层保护它,保护它不会反射,可以天然的防止反射和反序列化,可以利用反射创建对象,一般不用反射,没意义
步骤:
a. 私有化构造器
b. 使用枚举
Java单例模式
c. 创建静态工厂方法
Java单例模式
注意:单例不能new,因为构造器已经被私有化了,new会产生新的实例
验证单例
一个实例最好的验证方法就是用“==”,如果内存地址没有发生改变,则就是同一个实例(单例)
Java单例模式
如何选择单例:
单例对象占用资源少,不需要延时加载时:枚举好于饿汉式
单例对象占用资源多,需要延时加载时:静态内部类好于懒汉式