设计模式(四)单例模式

设计模式(四)单例模式

大鱼 2,640 2019-10-20

一、模式定义

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

二、模式结构

20160420_57175852e1d94.jpg

三、懒汉模式

public class Singleton {

    /**
     * 对保存实例的变量添加volatile的修饰
     */

    private volatile static Singleton instance = null;

    private Singleton(){

    }

    public static Singleton getInstance(){

//先检查实例是否存在,如果不存在才进入下面的同步块

        if(instance == null){

//同步块,线程安全的创建实例

            synchronized(Singleton.class){

//再次检查实例是否存在,如果不存在才真的创建实例

                if(instance == null){

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

优点: 懒加载,线程安全。
注: 实例必须有 volatile 关键字修饰,其保证初始化完全。

四、饿汉模式

public class Singleton {

//4:定义一个静态变量来存储创建好的类实例

//直接在这里创建类实例,只会创建一次

    private static Singleton instance = new Singleton();

//1:私有化构造方法,好在内部控制创建实例的数目

    private Singleton(){

    }

//2:定义一个方法来为客户端提供类实例

//3:这个方法需要定义成类方法,也就是要加static

//这个方法里面就不需要控制代码了

    public static Singleton getInstance(){

//5:直接使用已经创建好的实例

        return instance;

    }

}

优点: 饿汉模式天生是线程安全的,使用时没有延迟。
缺点: 启动时即创建实例,启动慢,有可能造成资源浪费。

五、Holder模式

public class Singleton {
    /**
     * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
     * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
     */
    private static class SingletonHolder{
        /**
         * 静态初始化器,由JVM来保证线程安全
         */
        private static Singleton instance = new Singleton();
    }
    /**
     * 私有化构造方法
     */
    private Singleton(){
    }
    public static  Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

优点: 将懒加载和线程安全完美结合的一种方式(无锁)。(推荐)

六、备注:

  1. 全局共享,独一份;

  2. 构造函数不暴露(如果暴露便不能保证一份),自己负责自己的构造;

  3. 懒汉式:Lazy load,用到才加载,非线程安全。如何保证线程安全呢

    1. synchronized getInstance()
    2. 双重检查加锁(volatile)
  4. 饿汉式:一开始就申请好,浪费了点资源,但其线程安全,执行效率高。

  5. Holder模式:改成内部类,由JVM保证线程安全性