对象声明实现单例模式
- 优点:
- 内存占用:实现简洁,没有额外的复杂逻辑带来的内存开销。
- 初始化时机:第一次使用时初始化,延迟加载,避免过早占用内存。
- 线程安全:Kotlin 保证对象声明是线程安全的,无需额外同步机制。
- 跨平台性:良好的跨平台性,在 JVM、Android、JavaScript 等平台都能很好工作。
- 缺点:无明显缺点,相对其他方式代码较紧凑,难以进行复杂初始化逻辑扩展。
- 示例:
object Singleton {
fun doSomething() {
println("Singleton is doing something")
}
}
伴生对象实现单例模式
- 优点:
- 内存占用:与类紧密关联,若类本身需要常驻内存,伴生对象也不会增加额外过多开销。
- 初始化时机:在类加载时初始化,可保证在类使用前就已存在。
- 线程安全:类加载机制保证线程安全。
- 跨平台性:跨平台表现良好。
- 缺点:
- 内存占用:若类加载过早,可能导致单例过早初始化,浪费内存。
- 初始化时机:不能实现延迟加载。
- 示例:
class SingletonCompanion {
companion object {
val instance: SingletonCompanion by lazy { SingletonCompanion() }
fun doSomething() {
println("SingletonCompanion is doing something")
}
}
}
懒汉式实现单例模式
- 优点:
- 内存占用:延迟初始化,只有在第一次使用时才占用内存。
- 初始化时机:按需初始化,有效节省内存。
- 缺点:
- 线程安全:非线程安全,多线程环境下需额外同步机制。
- 跨平台性:需要针对不同平台处理同步问题,跨平台性略差。
- 示例:
class LazySingleton {
companion object {
private var instance: LazySingleton? = null
fun getInstance(): LazySingleton {
if (instance == null) {
instance = LazySingleton()
}
return instance!!
}
}
}
饿汉式实现单例模式
- 优点:
- 线程安全:在类加载时就创建实例,天然线程安全。
- 跨平台性:跨平台性较好。
- 缺点:
- 内存占用:类加载时就初始化,即使未使用也占用内存。
- 初始化时机:不能延迟加载,可能导致不必要的资源浪费。
- 示例:
class EagerSingleton {
companion object {
val instance = EagerSingleton()
fun doSomething() {
println("EagerSingleton is doing something")
}
}
}
不同应用场景选择
- 对内存敏感且多线程环境:对象声明实现单例模式是首选,如 Android 应用中某些全局管理类。
- 需要与类紧密关联且无需延迟加载:伴生对象较合适,如工具类的单例实例。
- 单线程环境且希望延迟加载:懒汉式可满足需求,但要注意线程安全问题,适用于一些简单本地应用场景。
- 需要类加载时就确保实例存在:饿汉式能保证线程安全且快速获取实例,如数据库连接池初始化等场景。