设计模式 - 单例模式 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(){}
}
相关推荐
_李小白1 分钟前
【Android FrameWork】延伸阅读:CursorWindow的作用
android
介一安全13 分钟前
【Frida Android】实战篇14:非标准算法场景 Hook 教程
android·网络安全·逆向·安全性测试·frida
小虎牙00742 分钟前
关于Android Compose架构的思考
android·前端·mvvm
2501_915909061 小时前
手机崩溃日志导出的工程化体系,从系统级诊断到应用行为分析的多工具协同方法
android·ios·智能手机·小程序·uni-app·iphone·webview
木风小助理1 小时前
MySQL内存监控深度解析与故障排查实践
android·adb
灰鲸广告联盟1 小时前
APP广告变现定制化解决方案,助力收益提升与用户体验平衡
android·flutter·搜索引擎·ux
帅得不敢出门2 小时前
精简Android SDK(AOSP)的git项目提高git指令速度
android·java·开发语言·git·elasticsearch
2501_937189232 小时前
神马 9.0 2025 最新版源码系统:安全加固 + 二次开发友好
android·源码·开源软件·源代码管理·机顶盒
モンキー・D・小菜鸡儿3 小时前
Android 中 StateFlow 的使用
android·kotlin
二川bro3 小时前
字符串特性解析:Python不可变性引发的错误
android·开发语言·python