单例模式
单例模式是一个很常见的设计模式,尤其是在 Java 中应用非常广泛。单例模式的定义是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Java 中的单例模式
Java 中存在多种单例模式的实现方案,最经典的包括:
-
懒汉式
-
饿汉式
-
双重校验锁
饿汉式 / 静态单例
Java 中懒汉式单例如其名一样,“饿” 体现在不管单例对象是否存在,都直接进行初始化:
public final class SingleManager {
@NotNull
public static final SingleManager INSTANCE = new SingleManager();
private SingleManager() {}
public static SingleManager getInstance() {
return INSTANCE;
}
}
实际上,这也是静态单例。
懒汉式 / 延迟初始化
Java 中的懒汉式核心特点在于“懒” ,它不像饿汉式,无论 INSTANCE 是否已经存在值,都进行初始化;而是在调用 get 方法时,检查引用对象是否为空,如果为空再去初始化:
public final class SingleManager {
public static SingleManager INSTANCE;
private SingleManager() {}
public static SingleManager getInstance() {
if (INSTANCE == null) {
INSTANCE = new SingleManager();
}
return INSTANCE;
}
}
双重校验锁
public final class SingleManager {
// volatile 防止指令重排,确保原子操作的顺序性
public volatile static SingleManager INSTANCE;
private SingleManager() {}
public static SingleManager getInstance() {
// 第一次判空,减少进入同步锁的次数,提高效率
if (INSTANCE == null) {
// 确保同步
synchronized (SingleManager.class) {
// 确保加锁后,引用仍是空的
if (INSTANCE == null) {
INSTANCE = new SingleManager();
}
}
}
return INSTANCE;
}
}
Kotlin 中的单例模式
object 关键字
Kotlin 提供了比 Java 更方便的语法糖 object
关键字,能够更方便地实现单例模式:
object SingleManager {
fun main() {}
}
使用:
// used in kotlin
SingleManager.main()
// used in java
SingleManager.Companion.main();
如果要在 Java 中的使用方式与 Kotlin 使用方式一致,可以在方法上添加
@JvmStatic
注解:object SingleManager { @JvmStatic fun main() {} }
// used in java SingleManager.main();
object
关键字实现的单例,编译为 Java 字节码的实现是:
public final class SingleManager {
@NotNull
public static final SingleManager INSTANCE;
public final void main() {
}
private SingleManager() {
}
static {
SingleManager var0 = new SingleManager();
INSTANCE = var0;
}
}
这是一种标准的 Java 静态单例实现。
Kotlin 懒汉式
在一些特殊的情况,例如你的单例对象要保存一些不适合放在静态类中的引用,那么使用 object 就不是合适的方案了,例如,Android 中的上下文 Context 、View 都不适合在静态类中进行引用,IDE 也会提醒你这样会造成内存泄漏:
一种好的解决方案是在 Kotlin 中使用懒汉式的写法:
class SingleManager {
companion object {
private var instance: SingleManager? = null
fun getInstance(): SingleManager {
if (instance == null) {
instance = SingleManager()
}
return instance!!
}
}
var view: View? = null
}
但是这样仍然会提醒你不要引用:
但如果引用的对象是你自定义的 View :
class BaseView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs)
在 kotlin 中懒汉式是不会提示你的:
可以看出,使用 object 关键字,仍然会飘黄,提醒你可能存在内存泄漏。
本质上来说,没有提示实际上也是存在内存泄漏的隐患的。 虽然可以骗过 IDE 但不应该欺骗自己。
写在最后
Kotlin 作为一门更新的 JVM 语言,它提供了很多语法糖突破了 Java 的一些固定写法,有些设计模式已经不再适合新的语言(例如 Builder 模式在 Kotlin 中很少会出现了)。虽然新语言简化了代码的复杂度、简化了写法,但不能简化知识点,例如,使用 Kotlin 需要一个线程安全的单例,仍然可以使用双重校验锁的写法。本质上还是要搞清楚底层逻辑。
作者:自动化BUG制造器
链接:https://juejin.cn/post/7200708877389070395
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓