【设计模式04】单例模式

前言

整个系统中只会出现要给实例,比如Spring中的Bean基本都是单例的

UML类图

代码示例

java 复制代码
package com.sw.learn.pattern.B_create.c_singleton;


public class Main {
    public static void main(String[] args) {
        // double check locking 线程安全+懒加载 ⭐️
//        SingletonDCL instance = SingletonDCL.getInstance();

        // 静态内部类 线程安全+懒加载 ⭐️⭐️
//        Singleton s1 = Singleton.getInstance();
//        Singleton s2 = Singleton.getInstance();
//        System.out.println(s1 == s2); // true

        // 枚举类  线程安全+饿汉式 ⭐️⭐️⭐️
//        SingletonEnum.INSTANCE.doSomething();

        // 基于枚举内部类的懒汉式单例模式 ⭐️⭐️⭐️⭐️
        BeanContainer instance2 = BeanContainer.getInstance();
        BeanContainer instance3 = BeanContainer.getInstance();
        System.out.println(instance2 == instance3); // true

    }
}

class Singleton {
    // 私有构造方法,防止外部实例化
    private Singleton() {
        System.out.println("Singleton constructor called.");
    }

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

    // 对外提供获取实例的方法
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

class SingletonDCL {

    // 使用 volatile 防止初始化时指令重排序,确保线程安全
    private static volatile SingletonDCL instance;

    private SingletonDCL() {
        System.out.println("SingletonDCL constructor called.");
    }

    public static SingletonDCL getInstance() {
        if (instance == null) { // 第一次检查(不加锁) 提高性能
            synchronized (SingletonDCL.class) {
                if (instance == null) { // 第二次检查(加锁后再检查) 防止多个线程同时通过第一层检查后并发创建;
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}

enum SingletonEnum {
    INSTANCE;

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

// 枚举编译后效果
//final class SingletonEnum2 extends Enum<SingletonEnum2> {
//    public static final SingletonEnum2 INSTANCE = new SingletonEnum2("INSTANCE", 0);
//
//    private SingletonEnum2(String name, int ordinal) {
//        super(name, ordinal);
//    }
//}

class BeanContainer {
    // 调用getInstance方法时,第一次初始化ContainerHolder枚举类,初始的时候执行构造方法,实例化BeanContainer对象

    /**
     * 第一步:调用 ContainerHolder.HOLDER
     * JVM 首次访问 ContainerHolder 时会触发类加载。
     * <p>
     * 内部类不会在外部类加载时加载,只有在首次访问时才加载(这就是懒加载)。
     * <p>
     * 枚举类加载也是线程安全的,JVM 会保证枚举类只加载一次,不会有并发初始化问题。
     *
     * @return
     */
    public static BeanContainer getInstance() {
        return ContainerHolder.HOLDER.instance;
    }

    private enum ContainerHolder {
        HOLDER; // 容器,装载了BeanContainer对象
        /**
         * 第二步:加载 enum ContainerHolder
         * 枚举类 ContainerHolder 加载时,会创建一个 enum 常量 HOLDER。
         */
        private BeanContainer instance;

        ContainerHolder() {
            instance = new BeanContainer(); // 会被执行一次,初始化 instance, 即 ContainerHolder.HOLDER 被加载时。
        }
    }
}
相关推荐
剧中有戏10 小时前
抽象工厂模式从入门到精通:一个多云存储案例的完整剖析(修订版)
设计模式
breeze jiang13 小时前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
MC皮蛋侠客14 小时前
Redis 系列(八):缓存设计模式与一致性——从 Cache Aside 到防雪崩
redis·缓存·设计模式
meilindehuzi_a15 小时前
WebGPU DeepSeek项目实战(二):用单例模式加载Tokenizer并转发下载进度
单例模式·typescript·react
莫得感情 o15 小时前
设计模式 18 · 状态模式
设计模式·状态模式
莫得感情 o16 小时前
设计模式 17 · 责任链模式
设计模式·责任链模式
用户938515635071 天前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformer.js 全链路实战
前端·设计模式·typescript
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-04-工厂方法模式(业务实战篇)
java·设计模式·工厂方法模式·架构设计·代码解耦
今天的砖头有点烫手啊1 天前
AI Agent 开发实战(十):Agent 设计模式(ReAct / Plan-Execute / Reflection)
人工智能·react.js·设计模式
董员外2 天前
RAG 系统进化论(十):可运营 RAG,从原型到长期运行的知识系统
人工智能·后端·设计模式