设计模式之单例模式

设计模式之单例模式

编码文章call10242025-06-24 12:15:2411A+A-

1 介绍

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

2 实现步骤

所有的单例实现都包含以下两个相同的步骤:

  • 将默认构造方法设为私有,防止其他对象使用new直接创建对象。
  • 新建一个静态构建方法作为构造函数。函数调用私有构造方法来创建对象,并将其保存在一个静态成员变量中。之后所有对于该函数的调用将返回这一缓存对象。

UML类图实现如下:

3 八种实现方式

3.1 饿汉式(静态常量)

/**
 * 是否 Lazy 初始化:否
 * 是否多线程安全:是
 * 实现难度:易
 * JDK中的Runtime就是使用的这种模式
 */
public class Singleton1 {
    // 2 本类内部创建对象实例
    private static final Singleton1 instance = new Singleton1();
    // 1 构造器私有化,外部不能new
    private Singleton1(){}
    // 3 提供一个公有的静态方法,返回实例对象
    public static Singleton1 getInstance(){
        return instance;
    }
}

3.2 饿汉式(静态代码块)

/**
 * 是否 Lazy 初始化:否
 * 是否多线程安全:是
 * 实现难度:易
 */
public class Singleton2 {
    // 2 本类内部创建对象实例
    private static Singleton2 instance;
    static {
        instance = new Singleton2();
    }
    // 1 构造器私有化,外部不能new
    private Singleton2(){}
    // 3 提供一个公有的静态方法,返回实例对象
    public static Singleton2 getInstance(){
        return instance;
    }
}

饿汉式单例优缺点如下:

  • 优点
    • 单例对象的创建是线程安全的。
    • 获取单例对象的方法不需要加锁。
    • 代码实现简单。
  • 缺点
    • 单例对象的创建不是懒加载机制。

不管程序是否需要这个对象的实例,总是在类加载的时候就先创建好实例,就像不管一个人想不想吃东西,都要把吃的先买好,如同饿怕了的恶汉一样,因此叫饿汉式。

3.3 懒汉式(线程不安全)

/**
 * 是否 Lazy 初始化:是
 * 是否多线程安全:否
 * 实现难度:易
 */
public class Singleton3 {
    private static Singleton3 instance;
    private Singleton3(){}
    public static Singleton3 getInstance(){
        if (instance==null){
            instance = new Singleton3();
        }
        return instance;
    }
}

3.4 懒汉式(线程安全,同步方法)

/**
 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 实现难度:易
 */
public class Singleton4 {
    private static Singleton4 instance;
    private Singleton4(){}
    public static synchronized Singleton4 getInstance(){
        if (instance==null){
            instance = new Singleton4();
        }
        return instance;
    }
}

3.5 懒汉式(线程安全,同步代码块)

/**
 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 实现难度:易
 */
public class Singleton5 {
    private static Singleton5 instance;
    private Singleton5(){}
    public static Singleton5 getInstance(){
        if (instance==null){
            synchronized (Singleton5.class) {
                instance = new Singleton5();
            }
        }
        return instance;
    }
}

懒汉式单例优缺点如下:

  • 优点
    • 对象的创建是线程安全的。
    • 支持懒加载机制。
  • 缺点
    • 获取对象的方法上了锁,影响并发度。

当程序需要这个实例的时候才去创建对象,就如同一个人懒到饿的不行才去吃东西,因此叫懒汉式。

3.6 双检锁/双重校验锁

/**
 * JDK 版本:JDK1.5 起
 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 实现难度:较复杂
 */
public class Singleton6 {
    private static volatile Singleton6 instance;
    private Singleton6(){}
    public static Singleton6 getInstance(){
        if(instance==null){
            synchronized (Singleton6.class){
                if(instance==null){
                    instance = new Singleton6();
                }
            }
        }
        return instance;
    }
}

双重校验锁单例优缺点如下:

  • 优点
    • 对象的创建是线程安全的。
    • 支持懒加载机制。
    • 获取对象的方法不需要加锁。
  • 缺点
    • 实现复杂。

3.7 静态内部类

/**
 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 实现难度:一般
 */
public class Singleton7 {
    private Singleton7(){}
    private static class SingletonHolder{
        private static final Singleton7 INSTANCE = new Singleton7();
    }
    public static Singleton7 getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

静态内部类单例优点如下:

  • 优点
    • 对象的创建时线程安全的。
    • 支持懒加载机制。
    • 获取对象的方法不需要加锁。

3.8 枚举

/**
 * JDK 版本:JDK1.5 起
 * 是否 Lazy 初始化:否
 * 是否多线程安全:是
 * 实现难度:易
 */
public enum Singleton8 {
    INSTANCE;
    public void whateverMethod() {
       System.out.println(Thread.currentThread().getName()+":"+this);
    }
}

4 在JDK中的使用

在JDK中有Runtime类,这个类就使用了饿汉式静态常量的实现方式,核心代码如下:

// JDK中的RunTime类
public class Runtime {
  // 定义了一个静态的变量
	private static Runtime currentRuntime = new Runtime();
  // 一个私有的构造器
  private Runtime() {}
  // 获取唯一实例的静态方法
  public static Runtime getRuntime() {
    return currentRuntime;
  }
}

5 总结

对于单例模式核心概念有三点:单例模式是一种创建型的设计模式。在某个范围内,一个类只有一个实例存在。某个范围内,只提供一个访问实例的全局节点,这个范围可以是进程、线程、集群和类加载器。对于其实现方式,每个方式都有自己的优缺点,大家在使用的时候,可以根据具体的实际场景来选择,建议大家记住双重校验锁和静态内部类的实现方式。

【温馨提示】

点赞+收藏文章,关注我并私信回复【面试题解析】,即可100%免费领取楼主的所有面试题资料!

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4