设计模式 - 单例模式 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(){}
}
相关推荐
xiangpanf10 分钟前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx3 小时前
安卓线程相关
android
消失的旧时光-19433 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon4 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon5 小时前
VSYNC 信号完整流程2
android
dalancon5 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013846 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android6 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才7 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶7 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle