23种设计模式之【单例模式模式】-核心原理与 Java实践

文章目录

单例模式(Singleton Pattern)

单例模式是 23 种设计模式中的一种创建型模式,其核心思想是确保一个类在整个应用中只有一个实例,并提供一个全局访问点。这种模式常用于管理共享资源(如配置信息、线程池、日志对象等),避免资源竞争或重复创建带来的性能问题。

核心原理

  • 私有构造函数:
    阻止外部通过new关键字创建实例,确保只能通过类自身提供的方法获取实例
  • 静态私有实例:
    在类内部维护唯一的实例对象,通常为静态变量
  • 公共静态访问方法:
    提供全局访问点,确保返回的是同一个实例
    负责实例的创建(延迟初始化或饿汉式初始化)

单例模式的核心是 "唯一性" 与 "全局访问",通过控制实例创建过程,保证在任何情况下都只有一个实例存在。

Java 实践示例

下面实现几种常见的单例模式变体,各有其适用场景:

java 复制代码
package com.example.demo;

public class SingletonPattern {

    public static void main(String[] args) {
        // 测试枚举单例
        EnumSingleton.INSTANCE.doSomething();

        // 测试静态内部类单例
        StaticInnerClassSingleton instance1 = StaticInnerClassSingleton.getInstance();
        StaticInnerClassSingleton instance2 = StaticInnerClassSingleton.getInstance();
        System.out.println("静态内部类单例是否相同:" + (instance1 == instance2));
    }

    // 1. 饿汉式单例(线程安全,类加载时初始化)
    public static class EagerSingleton {
        // 类加载时就初始化实例
        private static final EagerSingleton INSTANCE = new EagerSingleton();

        // 私有构造函数,防止外部实例化
        private EagerSingleton() {}

        // 公共访问方法
        public static EagerSingleton getInstance() {
            return INSTANCE;
        }
    }

    // 2. 懒汉式单例(基础版,线程不安全)
    public static class LazySingleton {
        private static LazySingleton instance;

        private LazySingleton() {}

        // 非线程安全,多线程环境下可能创建多个实例
        public static LazySingleton getInstance() {
            if (instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    }

    // 3. 线程安全的懒汉式(同步方法,性能较低)
    public static class ThreadSafeLazySingleton {
        private static ThreadSafeLazySingleton instance;

        private ThreadSafeLazySingleton() {}

        // 同步方法保证线程安全,但每次调用都加锁,性能差
        public static synchronized ThreadSafeLazySingleton getInstance() {
            if (instance == null) {
                instance = new ThreadSafeLazySingleton();
            }
            return instance;
        }
    }

    // 4. 双重检查锁定(DCL,线程安全且高性能)
    public static class DoubleCheckedLockingSingleton {
        // volatile关键字防止指令重排序
        private static volatile DoubleCheckedLockingSingleton instance;

        private DoubleCheckedLockingSingleton() {}

        // 双重检查:减少同步开销,只在实例未创建时加锁
        public static DoubleCheckedLockingSingleton getInstance() {
            if (instance == null) {  // 第一次检查,无锁
                synchronized (DoubleCheckedLockingSingleton.class) {
                    if (instance == null) {  // 第二次检查,有锁
                        instance = new DoubleCheckedLockingSingleton();
                    }
                }
            }
            return instance;
        }
    }

    // 5. 静态内部类单例(推荐,线程安全且延迟初始化)
    public static class StaticInnerClassSingleton {
        // 私有构造函数
        private StaticInnerClassSingleton() {}

        // 静态内部类,只有在调用getInstance()时才会加载
        private static class SingletonHolder {
            private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
        }

        // 全局访问点
        public static StaticInnerClassSingleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    // 6. 枚举单例(最佳实践,防止反射和序列化破坏单例)
    public enum EnumSingleton {
        INSTANCE;  // 枚举实例天生单例

        // 可以添加其他方法
        public void doSomething() {
            System.out.println("枚举单例执行操作");
        }
    }
}

单例模式的关键问题

  • 线程安全:
    多线程环境下需保证实例唯一,最简单的方式是使用枚举或静态内部类
    DCL 模式需配合volatile关键字防止指令重排序导致的问题
  • 防止反射破坏:
    私有构造函数可被反射调用(通过setAccessible(true))
    枚举单例天然防止反射破坏,其他实现需在构造函数中添加防重入逻辑
  • 防止序列化破坏:
    实现Serializable接口的单例,反序列化时可能创建新实例
    解决方案:重写readResolve()方法返回原有实例
  • 单例与依赖注入:
    单例模式可能与依赖注入框架冲突,需谨慎使用
    可通过容器管理单例(如 Spring 的@Singleton)

单例模式的应用场景

工具类:如日志工具类Logger,全局只需要一个实例

配置管理:应用配置类Config,集中管理配置信息

线程池:ThreadPool全局唯一,避免资源浪费

数据库连接池:ConnectionPool共享连接资源

缓存:应用级缓存实例CacheManager

GUI 组件:如应用程序的主窗口MainFrame

单例模式是最简单的设计模式之一,但实现时需注意线程安全、反射攻击等问题。在实际开发中,枚举单例和静态内部类单例是推荐的实现方式,既能保证线程安全,又具有良好的性能。

相关推荐
Chan162 小时前
【 设计模式 | 行为型模式 观察者模式 】
java·spring boot·后端·spring·观察者模式·设计模式·idea
thginWalker2 小时前
Java 热门面试题200道之JVM(7 题)
java·jvm
fengdongnan2 小时前
JVM 类加载器详解
java·jvm·类加载器
安然~~~3 小时前
常见的【垃圾收集算法】
java·jvm
低调小一3 小时前
理解 JVM 的 8 个原子操作与 `volatile` 的语义
java·jvm
Familyism3 小时前
Java虚拟机——JVM
java·开发语言·jvm
^辞安3 小时前
什么是Mvcc
java·数据库·mysql
烈风3 小时前
009 Rust函数
java·开发语言·rust
这次选左边3 小时前
Flutter混合Android开发Release 打包失败GeneratedPluginRegistrant.java,Plugin不存在
android·java·flutter