设计模式 - 单例模式 Singleton Pattern

一、概念

确保一个类只有一个实例,并提供全局访问点,该类负责创建自身对象,同时保证仅单个对象被创建,且可直接访问(无需实例化)。

|----|-----------------------------------------|
| 优点 | 内存中仅一个实例,减少内存开销(如频繁创建/销毁的对象)。 |
| 优点 | 避免资源多重占用(如写文件操作)。 |
| 缺点 | 无接口,不能继承,与单一职责原则冲突(一个类需同时关心内部逻辑和实例化方式)。 |

1.1 不同单例区别

|---------|-------------------------------------------------------------------------|
| 饿汉单例 | 最简洁的实现,使用Kotlin的object关键字,类加载时就初始化实例,线程安全,适合简单的单例,不依赖外部参数,启动时就需要准备好的场景。 |
| 懒汉单例 | 延迟初始化,第一次使用时才创建实例,需要使用synchronized保证线程安全,适合初始化成本高,不常使用的单例。 |
| 双重校验锁单例 | 结合了懒加载和高效的线程安全,减少了同步块的开销,只有第一次初始化时才会进入同步块,适合高性能要求的多线程环境。 |
| 静态内部类单例 | 利用类加载机制保证线程安全,延迟初始化,只有在调用getInstance()时才会加载内部类,实现简洁,性能优良。 |
| 枚举单例 | 天然防止反射和序列化攻击,是最安全的单例实现,线程安全,实现简单,适合需要高度安全性的场景,但灵活性稍差。 |

1.2 Android 使用场景

|---------------|---------------------------------------------------------|
| Application实例 | 整个应用生命周期内唯一的Application对象,用于全局状态管理(如初始化第三方库、存储全局数据)。 |
| 工具类 | 如ToastUtil、LogUtil等工具类,通过单例避免重复创建,统一管理资源(如Toast的上下文引用)。 |
| 数据库助手类 | SQLiteOpenHelper通过单例确保数据库连接唯一,避免多实例导致的锁冲突或资源泄露。 |

二、实现

1.1 饿汉单例

Kotlin 复制代码
object Demo {
    const val NAME = ""
    fun show() {}
}

1.2 懒汉单例

Kotlin 复制代码
class Demo private constructor() {
    companion object {
        private var instance: Demo? = null
        //线程安全获取实例
        @Synchronized
        fun getInstance(): Demo {
            if (instance == null) instance = Demo()
            return instance!!
        }
    }
}

by lazy 版

Kotlin 复制代码
class Demo private constructor() {
    companion object {
        val instance by lazy { Demo() }
    }
}

1.3 双重校验锁单例

Kotlin 复制代码
class Demo private constructor() {
    companion object {
        // volatile确保多线程环境下的可见性
        @Volatile
        private var instance: Demo? = null
        fun getInstance(): Demo {
            // 第一次检查,避免不必要的同步
            if (instance == null) {
               synchronized(Demo::class.java) {
                   // 第二次检查,确保只创建一个实例
                   if (instance == null) instance == Demo()
               } 
            }
            return instance!!
        }
    }
}

1.4 静态内部类单例

Kotlin 复制代码
class Demo private constructor() {
    companion object {
        fun getInstance(): Demo = Holder.INSTANCE
    }
    private object Holder {
        val INSTANCE = Demo()
    }
}

1.5 枚举单例

Kotlin 复制代码
enum class Demo {
    INSTANCE;
    fun show(){}
}
相关推荐
_李小白11 分钟前
【android opencv学习笔记】Day 17: 目标追踪(MeanShift)
android·opencv·学习
用户86022504674721 小时前
AI 分析头部APP系统优化框架
android
用户86022504674721 小时前
AI分析头部APP优化框架
android
2501_916007474 小时前
iOS开发中抓取HTTPS请求的完整解决方法与步骤详解
android·网络协议·ios·小程序·https·uni-app·iphone
lvronglee6 小时前
【数字图传第四步】Android App查看图传视频
android·音视频
90后的晨仔7 小时前
Android 程序入口与核心组件详解
android
90后的晨仔7 小时前
Kotlin 简介与开发环境搭建
android
BU摆烂会噶7 小时前
【LangGraph】House_Agent 实战(四):预定流程 —— 中断与人工干预
android·人工智能·python·langchain
AI玫瑰助手7 小时前
Python运算符:比较运算符(等于不等等于大于小于)与返回值
android·开发语言·python
new_dev8 小时前
Python实现Android自动化打包工具:加固、签名、多渠道一键完成
android·python·自动化