Java 设计模式:单例模式(Singleton Pattern)

Java 设计模式:单例模式(Singleton Pattern)

_
本文内容由 AI 辅助生成。

1. 单例模式概述

定义:确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

核心要点

  • 私有构造函数

  • 静态私有实例

  • 公共静态获取方法

2. 实现方式

2.1 饿汉式(Eager Initialization)

public class EagerSingleton {
    // 在类加载时就创建实例
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    
    // 私有构造函数
    private EagerSingleton() {}
    
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

优点:线程安全,实现简单
缺点:可能造成资源浪费(即使不使用也会创建实例)

2.2 懒汉式(Lazy Initialization)- 非线程安全

public class LazySingleton {
    private static LazySingleton instance;
    
    private LazySingleton() {}
    
    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

缺点:多线程环境下不安全

2.3 懒汉式 - 线程安全(同步方法)

public class SynchronizedSingleton {
    private static SynchronizedSingleton instance;
    
    private SynchronizedSingleton() {}
    
    // 整个方法加锁,性能较差
    public static synchronized SynchronizedSingleton getInstance() {
        if (instance == null) {
            instance = new SynchronizedSingleton();
        }
        return instance;
    }
}

缺点:每次调用都要同步,性能开销大

2.4 双重检查锁定(Double-Checked Locking)

public class DoubleCheckSingleton {
    // volatile 确保多线程环境下的可见性和禁止指令重排序
    private static volatile DoubleCheckSingleton instance;
    
    private DoubleCheckSingleton() {}
    
    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

优点:线程安全,性能较好
注意:必须使用 volatile 关键字

2.5 静态内部类(推荐)

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

优点

  • 线程安全

  • 延迟加载

  • 性能优秀

  • 代码简洁

2.6 枚举实现(最安全)

public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

// 使用方式
EnumSingleton.INSTANCE.doSomething();

优点

  • 天然线程安全

  • 防止反射攻击

  • 防止序列化破坏单例

  • 代码最简洁

3. 扩展与高级话题

3.1 防止反射破坏单例

public class ReflectionSafeSingleton {
    private static volatile ReflectionSafeSingleton instance;
    
    private ReflectionSafeSingleton() {
        // 防止通过反射创建多个实例
        if (instance != null) {
            throw new RuntimeException("Use getInstance() method to create instance!");
        }
    }
    
    public static ReflectionSafeSingleton getInstance() {
        if (instance == null) {
            synchronized (ReflectionSafeSingleton.class) {
                if (instance == null) {
                    instance = new ReflectionSafeSingleton();
                }
            }
        }
        return instance;
    }
}

3.2 防止序列化破坏单例

import java.io.Serializable;

public class SerializableSafeSingleton implements Serializable {
    private static final long serialVersionUID = 1L;
    private static volatile SerializableSafeSingleton instance;
    
    private SerializableSafeSingleton() {}
    
    public static SerializableSafeSingleton getInstance() {
        if (instance == null) {
            synchronized (SerializableSafeSingleton.class) {
                if (instance == null) {
                    instance = new SerializableSafeSingleton();
                }
            }
        }
        return instance;
    }
    
    // 保证反序列化时返回同一个实例
    private Object readResolve() {
        return getInstance();
    }
}

3.3 泛型单例工厂

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class GenericSingletonFactory {
    private static final Map<Class<?>, Object> instances = new ConcurrentHashMap<>();
    
    @SuppressWarnings("unchecked")
    public static <T> T getInstance(Class<T> clazz) {
        return (T) instances.computeIfAbsent(clazz, k -> {
            try {
                return clazz.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException("Failed to create instance for " + clazz, e);
            }
        });
    }
}

// 使用示例
MyService service = GenericSingletonFactory.getInstance(MyService.class);

3.4 注册表式单例

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class RegistrySingleton {
    private static final Map<String, Object> registry = new ConcurrentHashMap<>();
    
    private RegistrySingleton() {}
    
    public static void register(String key, Object instance) {
        registry.put(key, instance);
    }
    
    public static Object getInstance(String key) {
        return registry.get(key);
    }
    
    public static boolean contains(String key) {
        return registry.containsKey(key);
    }
}

4. 单例模式的适用场景

适用场景:

  • 配置管理器:应用程序配置只需要一份

  • 日志记录器:统一的日志输出管理

  • 数据库连接池:避免重复创建连接

  • 线程池:统一管理线程资源

  • 缓存管理器:全局缓存控制

  • 对话框/窗口管理器:确保界面元素唯一性

不适用场景:

  • 对象需要频繁创建和销毁

  • 对象状态经常变化且需要多个实例

  • 分布式系统中的单例(需要考虑集群环境)

5. 单例模式的优缺点

优点:

  • 内存节约:确保只有一个实例,节省内存

  • 全局访问:提供全局访问点,方便使用

  • 控制实例数量:严格控制对象创建

缺点:

  • 违反单一职责原则:既要管理业务逻辑,又要管理实例创建

  • 难以测试:单例持有状态,影响单元测试的独立性

  • 隐藏依赖关系:通过静态方法获取,依赖关系不明显

  • 扩展困难:单例类通常不能被继承

6. 最佳实践建议

  1. 优先考虑枚举实现:最安全、最简洁

  2. 次选静态内部类:延迟加载且线程安全

  3. 避免使用懒汉式的同步方法:性能太差

  4. 考虑使用依赖注入框架:如 Spring 的 @Scope("singleton")

  5. 注意序列化和反射的安全性

  6. 在分布式环境中谨慎使用:考虑 Redis 等分布式解决方案

7. Spring 中的单例

@Component
@Scope("singleton") // 默认就是 singleton
public class SpringSingletonService {
    // Spring 容器管理的单例
}

Spring 的单例是在 IOC 容器级别,而不是 JVM 级别,这是重要的区别。

Java-集合 2026-01-07
财务概念释义-会计 2026-01-08

评论区

© 2026 何歡囍