哇喔!20种单例模式的实现与变异总结

大家好,我是 V 哥。再聊到单例模式,你可能会说老掉牙的问题有啥值得讲的,可能还真有,笔试题上镜率极高的一道题还在考,你的回答如何能从网络上千遍一律的回答中脱颖而出,成为卷王,是不是得来点不一样的东西呢,这20种单例模式的实现与变异总结,也许可以让你有新的发现,收藏起来吧。

V 哥推荐:2024 最适合入门的 JAVA 课程

单例设计模式确保一个类在整个系统中只存在一个实例,通常用于全局访问的共享资源,如数据库连接、配置文件读取、线程池等。以下V 哥总结的20种不同的实现,来看一下:

1. 饿汉式(Eager Initialization)

  • 实现 :在类加载时就创建单例实例,使用finalstatic关键字定义。
  • 特点:线程安全;类加载时实例即创建,可能会导致不必要的内存占用。
java 复制代码
public class SingletonEager {
    private static final SingletonEager instance = new SingletonEager();
    private SingletonEager() {}
    public static SingletonEager getInstance() {
        return instance;
    }
}

2. 懒汉式(Lazy Initialization)

  • 实现:在首次使用时才创建实例。
  • 特点:延迟加载,节省资源;不是线程安全的,适合单线程环境。
java 复制代码
public class SingletonLazy {
    private static SingletonLazy instance;
    private SingletonLazy() {}
    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

3. 线程安全的懒汉式(Synchronized Lazy Initialization)

  • 实现 :在懒汉式基础上加入sychronized关键字,确保多线程环境的安全。
  • 特点:线程安全,但加锁会影响性能。
java 复制代码
public class SingletonLazySync {
    private static SingletonLazySync instance;
    private SingletonLazySync() {}
    public static synchronized SingletonLazySync getInstance() {
        if (instance == null) {
            instance = new SingletonLazySync();
        }
        return instance;
    }
}

4. 双重检查锁(Double-Checked Locking)

  • 实现:在获取实例时先判断是否为空,再加锁创建实例。
  • 特点:在多线程情况下性能更高,线程安全;适合多线程环境。
java 复制代码
public class SingletonDCL {
    private static volatile SingletonDCL instance;
    private SingletonDCL() {}
    public static SingletonDCL getInstance() {
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}

5. 静态内部类(Static Inner Class)

  • 实现:利用类加载机制,延迟创建实例。
  • 特点:线程安全,懒加载,效率高。
java 复制代码
public class SingletonInnerClass {
    private SingletonInnerClass() {}
    private static class Holder {
        private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();
    }
    public static SingletonInnerClass getInstance() {
        return Holder.INSTANCE;
    }
}

6. 枚举单例(Enum Singleton)

  • 实现:使用枚举类型实现单例,JVM保证了线程安全。
  • 特点:线程安全、防止反射和序列化破坏单例,是最佳实现方式之一。
java 复制代码
public enum SingletonEnum {
    INSTANCE;
    public void someMethod() {
        // some code
    }
}

7. 使用容器实现单例(Container Singleton)

  • 实现:使用容器(如Map)存储类对象。
  • 特点:适合管理多种类型的单例;实现复杂度增加,使用场景较特殊。
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class SingletonContainer {
    private static Map<String, Object> instanceMap = new HashMap<>();
    private SingletonContainer() {}
    public static void registerInstance(String key, Object instance) {
        if (!instanceMap.containsKey(key)) {
            instanceMap.put(key, instance);
        }
    }
    public static Object getInstance(String key) {
        return instanceMap.get(key);
    }
}

除了常见的7种实现方式,还有几种不同的单例模式变体,适合更复杂的使用场景:

8. 线程本地单例(ThreadLocal Singleton)

  • 实现 :使用ThreadLocal变量保证每个线程有自己的单例实例。
  • 特点:每个线程会有一个单例实例,不同线程之间的实例是独立的;适合线程隔离的数据,如数据库连接或特定线程的上下文信息。
java 复制代码
public class SingletonThreadLocal {
    private static final ThreadLocal<SingletonThreadLocal> threadLocalInstance =
            ThreadLocal.withInitial(SingletonThreadLocal::new);

    private SingletonThreadLocal() {}

    public static SingletonThreadLocal getInstance() {
        return threadLocalInstance.get();
    }
}

9. CAS实现的单例(CAS-based Singleton)

  • 实现 :利用java.util.concurrent.atomic.AtomicReference原子类实现无锁单例。
  • 特点:通过CAS保证线程安全,性能较高;适合高并发场景,但代码稍复杂。
java 复制代码
import java.util.concurrent.atomic.AtomicReference;

public class SingletonCAS {
    private static final AtomicReference<SingletonCAS> INSTANCE = new AtomicReference<>();

    private SingletonCAS() {}

    public static SingletonCAS getInstance() {
        while (true) {
            SingletonCAS current = INSTANCE.get();
            if (current != null) {
                return current;
            }
            current = new SingletonCAS();
            if (INSTANCE.compareAndSet(null, current)) {
                return current;
            }
        }
    }
}

10. 枚举双重锁单例(Enum Holder with DCL)

  • 实现 :结合Enum的延迟加载特性与双重检查锁来实现。
  • 特点 :利用Enum保证单例的序列化安全,结合DCL提高性能。适合对高性能和安全性要求极高的场景。
java 复制代码
public class SingletonEnumDCL {
    private SingletonEnumDCL() {}

    private enum Holder {
        INSTANCE;
        private final SingletonEnumDCL instance = new SingletonEnumDCL();
    }

    public static SingletonEnumDCL getInstance() {
        return Holder.INSTANCE.instance;
    }
}

11. 注册表式单例(Registry Singleton)

  • 实现 :通过注册表(如HashMap)集中管理多个不同类型的单例实例。
  • 特点:适合多单例实例的场景,类似于容器模式;复杂性较高,适合复杂的依赖管理系统。
java 复制代码
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SingletonRegistry {
    private static final Map<String, Object> registry = new ConcurrentHashMap<>();

    private SingletonRegistry() {}

    public static void registerSingleton(String key, Object instance) {
        registry.putIfAbsent(key, instance);
    }

    public static Object getSingleton(String key) {
        return registry.get(key);
    }
}

12. Bill Pugh单例(Bill Pugh Singleton)

  • 实现:通过静态内部类加载实例。
  • 特点:一种特殊的静态内部类实现,解决了饿汉式和懒汉式的缺点;线程安全、高效、延迟加载。
java 复制代码
public class SingletonBillPugh {
    private SingletonBillPugh() {}

    private static class SingletonHelper {
        private static final SingletonBillPugh INSTANCE = new SingletonBillPugh();
    }

    public static SingletonBillPugh getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

13. 反射防护单例(Reflection Proof Singleton)

  • 实现:通过枚举或特殊处理反射的方式来防止反射破坏单例。
  • 特点:保护单例不被反射攻击破坏,适合安全性要求较高的场景。
java 复制代码
public class SingletonReflectionProof {
    private static final SingletonReflectionProof INSTANCE = new SingletonReflectionProof();

    private SingletonReflectionProof() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Instance already created!");
        }
    }

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

14. 资源管理单例(Resource Management Singleton)

  • 实现 :在类的finalize方法中释放资源或做额外处理。
  • 特点:确保系统资源不会被过多实例浪费,适合资源有限的情况。
java 复制代码
public class SingletonResource {
    private static final SingletonResource INSTANCE = new SingletonResource();
    
    private SingletonResource() {
        // 初始化资源
    }

    public static SingletonResource getInstance() {
        return INSTANCE;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        // 释放资源
    }
}

除了以上列出的常见单例模式实现方式,还有一些变种实现和特殊情况的单例设计。

下面介绍一些更高级的实现方式

15. 接口代理单例(Interface Proxy Singleton)

  • 实现:通过动态代理生成单例实例,控制对单例对象的访问。
  • 特点:适用于复杂的业务场景,可以在代理中加入权限控制、日志等额外逻辑。
java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SingletonProxy {
    private static final MySingletonInterface INSTANCE = 
        (MySingletonInterface) Proxy.newProxyInstance(
            MySingletonInterface.class.getClassLoader(),
            new Class[]{MySingletonInterface.class},
            new SingletonHandler(new MySingleton())
        );

    private SingletonProxy() {}

    public static MySingletonInterface getInstance() {
        return INSTANCE;
    }

    private static class SingletonHandler implements InvocationHandler {
        private final MySingleton instance;

        public SingletonHandler(MySingleton instance) {
            this.instance = instance;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 可以在这里加入权限控制、日志等
            return method.invoke(instance, args);
        }
    }
}

interface MySingletonInterface {
    void doSomething();
}

class MySingleton implements MySingletonInterface {
    @Override
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

16. Service Locator单例(Service Locator Singleton)

  • 实现:Service Locator模式是一种设计模式,通过注册中心管理单例对象,避免直接依赖实例,便于松耦合和模块化。
  • 特点:更适合用于依赖注入和模块间解耦场景,适用于复杂系统中的组件管理。
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class ServiceLocator {
    private static final Map<Class<?>, Object> services = new HashMap<>();

    private ServiceLocator() {}

    public static <T> void registerService(Class<T> serviceClass, T instance) {
        services.put(serviceClass, instance);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getService(Class<T> serviceClass) {
        return (T) services.get(serviceClass);
    }
}

17. 对象池单例(Object Pool Singleton)

  • 实现:使用对象池模式,创建有限数量的单例对象,并在对象使用完毕后进行复用。
  • 特点:在需要复用固定数量资源时非常有效,如数据库连接池、线程池等。
java 复制代码
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class SingletonObjectPool {
    private static final int POOL_SIZE = 5;
    private static final Queue<SingletonObjectPool> pool = new ConcurrentLinkedQueue<>();

    static {
        for (int i = 0; i < POOL_SIZE; i++) {
            pool.add(new SingletonObjectPool());
        }
    }

    private SingletonObjectPool() {}

    public static SingletonObjectPool getInstance() {
        SingletonObjectPool instance = pool.poll();
        if (instance == null) {
            instance = new SingletonObjectPool();
        }
        return instance;
    }

    public void release() {
        pool.offer(this);
    }
}

18. 克隆防御单例(Clone-Proof Singleton)

  • 实现 :通过覆盖clone方法,防止克隆破坏单例模式。
  • 特点:保证单例对象无法通过克隆创建额外实例,防止了反射破坏单例的风险。
java 复制代码
public class SingletonCloneProof implements Cloneable {
    private static final SingletonCloneProof INSTANCE = new SingletonCloneProof();

    private SingletonCloneProof() {}

    public static SingletonCloneProof getInstance() {
        return INSTANCE;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Cannot clone singleton instance");
    }
}

19. 定时刷新单例(Time-Based Singleton Refresh)

  • 实现:在指定时间或条件下重新创建单例对象,通常用于缓存或短期需要重新加载的对象。
  • 特点:适合数据或配置需要定期更新的情况,确保每个时间段获得最新的单例实例。
java 复制代码
public class SingletonTimeBased {
    private static SingletonTimeBased instance;
    private static long lastCreatedTime = System.currentTimeMillis();
    private static final long REFRESH_INTERVAL = 30000; // 30 seconds

    private SingletonTimeBased() {}

    public static synchronized SingletonTimeBased getInstance() {
        if (instance == null || System.currentTimeMillis() - lastCreatedTime > REFRESH_INTERVAL) {
            instance = new SingletonTimeBased();
            lastCreatedTime = System.currentTimeMillis();
        }
        return instance;
    }
}

20. 弱引用单例(Weak Reference Singleton)

  • 实现 :使用WeakReference包装单例对象,允许Java垃圾收集器在内存不足时回收该对象。
  • 特点:适合内存敏感的场景,减少长时间未使用对象的内存占用,但对象可能会在不经意间被GC回收。
java 复制代码
import java.lang.ref.WeakReference;

public class SingletonWeakReference {
    private static WeakReference<SingletonWeakReference> instanceRef;

    private SingletonWeakReference() {}

    public static synchronized SingletonWeakReference getInstance() {
        SingletonWeakReference instance = (instanceRef == null) ? null : instanceRef.get();
        if (instance == null) {
            instance = new SingletonWeakReference();
            instanceRef = new WeakReference<>(instance);
        }
        return instance;
    }
}

最后

这些变种和扩展可以用来应对不同的使用场景,从安全性到性能需求再到资源管理需求。根据特定需求,可以选择或定制合适的单例实现方式。关注威哥爱编程,编程乐无边。

相关推荐
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔5 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社6 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖7 小时前
JDK 26 新特性详解
java·开发语言
马优晨8 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区10 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大10 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai11 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说11 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json