跳至主要內容

设计模式学习-单例模式

chenxi编程设计模式大约 2 分钟

什么是单例模式

  1. 一个类只有一个实例。即使用单例模式的类的构造方法必须是private,且类中含有一个当前类的静态成员变量。
  2. 自行实例化,并向整个系统提供这个实例。即使用单例模式的类的初始化必须在类的内部,且要对外提供一个公开的方法来提供该类的实例对象。

单例模式的多种实现方式

单例模式的实现方式有很多种,比较常见的:

  • 饿汉式(类加载时进行实例化)

  • 懒汉式(在第一次使用时再实例化)

  • 利用枚举类实现

    饿汉式的代码实现:

public class Singleton_01 {
    public static Singleton_01 INSTANCE = new Singleton_01();
    private Singleton_01() {}

    public static Singleton_01 getInstance() {
        return INSTANCE;
    }
}

懒汉式的代码实现:

使用懒汉式进行实现,为确保线程安全,需要使用synchronized上锁,确保使用单例模式的类仅会被实例化一次,这里会使用到双重检查锁,即不是给对外提供实例的方法上锁,而是在方法内部,主要目的是减少锁的粒度。在使用双重检查锁的时候,当前类的静态成员变量必须使用volatile进行修饰,避免因为指令重排序导致的线程安全问题。

public class Singleton_02 {
    private static volatile Singleton_02 INSTANCE;

    private Singleton_02() {}

    public static Singleton_02 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton_02.class) {
                if (INSTANCE == null) INSTANCE = new Singleton_02();
            }
        }

        return INSTANCE;
    }
}

利用枚举类的代码实现:

使用枚举类进行实现,主要借助于枚举类的特性,成员会使用staticfinal进行修饰,且构造方法私有化。和饿汉式有些相似,但代码量非常简洁。

public enum Singleton_03 {
    INSTANCE;
}

单例模式存在的问题

单例模式对于每个类一定只有一个实例吗?

不一定。
在分布式环境下,会有多个 JVM,每个 JVM 都有一个实例。
或是同一个 JVM 使用多个类加载器,同时加载了这个类。

单例模式不适用于有状态。

如果一个使用单例模式的类是有状态的,比如该类有个成员变量的值是 10,在某个地方用的时候,将其修改为了 20,但有可能在其他地方又被修改为了 30。
所以,一般使用单例模式的类都是无状态的,例如工具类。

上次编辑于:
贡献者: chenxi