设计模式 - 单例模式 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(){}
}
相关推荐
Kapaseker10 分钟前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴37 分钟前
Android17 为什么重写 MessageQueue
android
阿巴斯甜21 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android