二十三种设计模式(一)--单例模式

单例模式

单例模式的目的是保证应用全局都只能获取到唯一的一个实例

实现思路有三步:

  1. 私有化构造器, 防止外部实例化
  2. 内部实例化, 并将创建好的实例私有化存储
  3. 对外提供唯一的获取实例接口, 外部通过此接口只能获取唯一的实例对象
单例模式Java语言示例

使用Java编写单例模式要注意一下问题:

  1. 内存占用, 关注创建实例的时机, 当没用到类对象时, 不需要创建, 节省内存空间
  2. 是否线程安全, 多线程调用时, 要保证也仅仅有一个对象实例
  3. 关注获取实例对象的效率, 外部频繁多次调用接口时, 能否快速地返回实例对象
  4. 防止JVM虚拟机的指令重排优化导致创建的实例无法运行

双重检查方式:

java 复制代码
class Singleton01 {
    // 1. 加 volatile 禁止指令重排,保证实例创建的原子性可见性
    private static volatile Singleton01 instance = null;

    // 私有化构造器(防止反射破坏单例,可额外加限制)
    private Singleton01() {
        // 可选:防止反射创建多个实例(若无需防御反射,可省略)
        if (instance != null) {
            throw new IllegalStateException("单例实例已存在,禁止重复创建");
        }
    }

    public static Singleton01 getInstance() {
        // 2. 第一次检查:未加锁,快速判断(避免冗余锁竞争)
        if (instance == null) {
            // 3. 加锁:仅实例未创建时才加锁
            synchronized (Singleton01.class) {
                // 4. 第二次检查:防止多线程同时通过第一次检查后,重复创建
                if (instance == null) {
                    instance = new Singleton01(); // volatile 禁止此处指令重排
                }
            }
        }
        return instance;
    }
}

通过静态内部类方式实现:

java 复制代码
class Singleton02 {
    // 静态内部类:只有被调用时才加载,实现懒加载
    private static class SingletonHolder {
        private static final Singleton02 INSTANCE = new Singleton02();
    }

    private Singleton02() {}

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

最推荐的写法, 枚举单例:

java 复制代码
// 枚举单例(最简洁的安全单例)
enum EnumSingleton {
    // 唯一实例(枚举常量,全大写命名,可理解为单例的 INSTANCE)
    // 注意点: 传入参数只能在定义时传入, 如果想在获取实例时传入是不行的,
    // 比如: EnumSingleton obj = EnumSingleton.INSTANCE("枚举单例", 1);这种写法是错误的
    // 想要在运行时向单例实例中传入参数, 只能通过自定义setter方法的方式传入
    INSTANCE("单例名称", 1);

    // 枚举单例的成员属性(可选)
    private final String name;
    private final int code;

    // 枚举的构造器(默认 private,且只能是 private,无需显式声明)
    EnumSingleton(String name, int code) {
        this.name = name;
        this.code = code;
    }

    // 实例方法(供外部调用)
    public void doBusiness() {
        System.out.println("枚举单例执行逻辑:name=" + name + ", code=" + code);
    }

    //  getter 方法(访问私有属性,可选)
    public String getName() {
        return name;
    }

    public int getCode() {
        return code;
    }
}


// 调用示例 ---------------
EnumSingleton obj5 = EnumSingleton.INSTANCE;
obj5.doBusiness();
相关推荐
故事和你9143 分钟前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Configure-Handler1 小时前
buildroot System configuration
java·服务器·数据库
:Concerto2 小时前
JavaSE 注解
java·开发语言·sprint
电商API_180079052473 小时前
第三方淘宝商品详情 API 全维度调用指南:从技术对接到生产落地
java·大数据·前端·数据库·人工智能·网络爬虫
一点程序3 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
C雨后彩虹3 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试
2601_949809593 小时前
flutter_for_openharmony家庭相册app实战+我的Tab实现
java·javascript·flutter
vx_BS813303 小时前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_949868363 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
达文汐4 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣