创建型模式-单例模式

单例模式有两种常见的实现方式:饿汉式懒汉式。以下是它们的代码示例:

1. 饿汉式(Eager Initialization)

在类加载时就创建实例,线程安全,适用于单例对象耗费资源较小的场景。

public class SingletonEager {
    // 在类加载时就创建实例
    private static final SingletonEager instance = new SingletonEager();

    // 私有构造方法,防止外部实例化
    private SingletonEager() {}

    // 提供全局访问点
    public static SingletonEager getInstance() {
        return instance;
    }
}

优点

  • 简单直观
  • 线程安全,不需要同步

缺点

  • 即使不使用该实例,类加载时也会创建对象,可能造成资源浪费。

2. 懒汉式(Lazy Initialization)

在第一次调用 getInstance() 时才创建实例,适用于单例对象较耗资源且不一定每次都使用的场景。

2.1 线程不安全的懒汉式:
public class SingletonLazy {
    // 延迟初始化
    private static SingletonLazy instance;

    // 私有构造方法
    private SingletonLazy() {}

    // 提供全局访问点(线程不安全)
    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

优点

  • 按需加载,节省资源

缺点

  • 线程不安全,多个线程可能同时创建多个实例
2.2 线程安全的懒汉式(同步方法):
public class SingletonLazyThreadSafe {
    private static SingletonLazyThreadSafe instance;

    private SingletonLazyThreadSafe() {}

    // 通过同步锁保证线程安全
    public static synchronized SingletonLazyThreadSafe getInstance() {
        if (instance == null) {
            instance = new SingletonLazyThreadSafe();
        }
        return instance;
    }
}

优点

  • 线程安全,简单易懂

缺点

  • 每次获取实例都需要同步,性能开销较大
2.3 双重检查锁(Double-Check Locking):
public class SingletonLazyDoubleCheck {
    private static volatile SingletonLazyDoubleCheck instance;

    private SingletonLazyDoubleCheck() {}

    public static SingletonLazyDoubleCheck getInstance() {
        if (instance == null) {
            synchronized (SingletonLazyDoubleCheck.class) {
                if (instance == null) {
                    instance = new SingletonLazyDoubleCheck();
                }
            }
        }
        return instance;
    }
}

优点

  • 线程安全,且只在第一次创建时进行同步,性能较好

缺点

  • 代码较复杂,需要注意 volatile 的使用

3. 静态内部类(推荐使用)

静态内部类的方式结合了懒汉式和饿汉式的优点,线程安全且高效。

public class SingletonStaticInnerClass {
    private SingletonStaticInnerClass() {}

    // 静态内部类
    private static class SingletonHolder {
        private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();
    }

    public static SingletonStaticInnerClass getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

优点

  • 利用了类加载机制,保证线程安全
  • 延迟初始化,按需加载
  • 不需要同步,性能较高

这几种方式都可以实现单例模式,具体使用时可以根据项目的实际需求进行选择。

在 JDK 中,单例模式被广泛应用于很多核心类和工具类中。以下是一些经典的 JDK 类或组件使用单例模式的例子:

jdk中使用到的单例模式

1. java.lang.Runtime

Runtime 类用于与 JVM 交互,并提供了管理和控制 JVM 的方法。它使用了饿汉式单例。

Runtime runtime = Runtime.getRuntime();
  • 使用场景Runtime 提供了 JVM 相关的全局服务,比如执行操作系统命令、获取可用的内存和处理器数量等。
  • 实现:通过 getRuntime() 方法获取唯一实例,类加载时就创建实例。
2. java.awt.Desktop

Desktop 类提供了一些平台相关的桌面操作功能,如打开浏览器、邮件客户端等。它也是通过单例模式实现的。

Desktop desktop = Desktop.getDesktop();
  • 使用场景:用于与本地操作系统的桌面功能交互,如打开文件、发送邮件等。
  • 实现:通过 getDesktop() 方法获取唯一实例。
3. java.lang.System

System 类提供了许多静态方法,用于与系统环境交互,如读取环境变量、标准输入输出等。它虽然没有传统意义的 getInstance(),但其设计本质上是一种单例模式,主要通过静态方法提供系统服务。

System.out.println("Hello, World!");
  • 使用场景:处理标准输入输出流、系统属性、环境变量等。
  • 实现:通过静态方法提供全局访问,不允许实例化。
4. java.util.logging.LogManager

LogManager 类负责管理全局日志配置,确保整个应用程序中日志记录的一致性。

LogManager logManager = LogManager.getLogManager();
  • 使用场景:控制全局的日志配置,管理所有的 Logger 实例。
  • 实现:使用单例模式确保只有一个日志管理器实例在运行时存在。
5. java.sql.DriverManager

DriverManager 用于管理数据库驱动程序,并处理与数据库的连接请求。

Connection connection = DriverManager.getConnection(url, user, password);
  • 使用场景:管理数据库连接,加载和注册 JDBC 驱动程序。
  • 实现:通过静态方法管理数据库连接,全局管理驱动程序的加载。
6. java.util.Calendar

Calendar 类用来操作日期和时间的实例,在一些实现(如 GregorianCalendar)中也使用了单例模式。

Calendar calendar = Calendar.getInstance();
  • 使用场景:用于日期和时间的计算与操作。
  • 实现:通过 getInstance() 提供全局访问点。
7. java.nio.file.FileSystems

FileSystems 类用来管理文件系统的访问。

FileSystem fileSystem = FileSystems.getDefault();
  • 使用场景:获取文件系统的根路径,处理路径的文件操作。
  • 实现:通过 getDefault() 方法获取默认的文件系统,内部实现单例模式。

总结

这些 JDK 中的类,采用单例模式的原因通常是:

  • 确保系统中某个类只有一个实例,避免资源浪费。
  • 提供全局访问点,使得这些实例能够被多个地方访问和共享。
  • 方便管理与外部系统交互的资源,如日志管理器、数据库连接、文件系统、JVM 资源等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wrx繁星点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值