对照Java和Kotlin语法分点学习单例设计模式,读者结合目录详细解释知识点,欢迎学习交流!
目录
饿汉式
1.解释
“你真是饿了!”——声明单例对象的时候直接初始化变量
无线程安全问题,但是占内存,性能需优化!
2.实现逻辑
- 需要私有化构造函数
- 需要一个静态不可变的instance内部初始化这个类
- 提供一个静态获取instance静态对象的方法
3.具体实现
kotlin实现
companion object即使kotlin语法的静态类,随类只会加载一次
class UserManger private constructor(){
companion object{
private val instance = UserManger()
fun getInstance():UserManger{
return instance
}
}
}
Java实现
final关键字确保instance只会初始化一次,就是值不会再改变了
public class FileManager {
private FileManager(){ }
private static final FileManager instance = new FileManager();
public static FileManager getInstance(){
return instance;
}
}
线程安全懒汉式
1.解释
懒汉式是需要这个类对象才实例化,多线程会出现安全问题,我们应用都是线程安全版本懒汉式!
但是当一个线程获取锁,其他线程会等待,浪费资源
2.实现逻辑
- Kotlin使用伴生类,Java利用static,使得保存单例的变量和获取单例的方法随类仅加载一次
- kotlin中单例的成员变量为该类可选类型,初始化null;而Java会自动初始化其NULL
- Kotlin中需要重写instance系统定义get()来创建单例
- 获取单例方法上:Kotlin加@Synchronized注解,Java方法名直接加Synchronized修饰符
3.具体实现
kotlin实现
class UserManger private constructor(){
companion object{
private var instance :UserManger? = null
get() {
if (field == null){
field = UserManger()
}
return field
}
@Synchronized
fun gotInstance() = instance!!
}
}
Java实现
public class FileManager {
private FileManager(){ }
private static FileManager instance;
public static synchronized FileManager getInstance(){
if (instance == null){
instance = new FileManager();
}
return instance;
}
}
双重检查锁
1.解释
若已经实现单例对象,其他线程再获取锁,只会浪费性能,所以在获取锁前加一层逻辑判断
属于性能改良版的线程安全懒汉式——同时实现单例,性能,线程安全
2.实现逻辑
- 在线程安全懒汉式代码加锁之前,只需加一层判断“单例对象是否存在”,优化性能
3.Java具体实现
public class FileManager {
private FileManager(){ }
private static FileManager instance;
public static FileManager getInstance(){
if (instance == null){
synchronized(FileManager.class){
if (instance == null){
instance = new FileManager();
}
}
}
return instance;
}
}
懒加载
1.解释
懒加载作为Kotlin的特性,懒加载变量只有当被调用时才加载,而且只加载一次
2.实现逻辑
- 通过后缀by lazy (mode = ){ 初始化对象 }
- mode调用系统枚举类LazyThreadSafetyMode中 SYNCHRONIZED保证线程安全
3.Kotlin具体实现
class UserManger private constructor(){
companion object{
val instance:UserManger by lazy (mode = LazyThreadSafetyMode.SYNCHRONIZED){
UserManger()
}
}
}
静态内部类
1.解释
JVM 在加载外部类的过程中, 是不会加载静态内部类的。
只有内部类的属性/方法被调用时才会被加载, 唯一一次并始化其静态属性。
2.实现逻辑
- 定义静态内部类,内部类中实例化单例对象
- 通过静态方法将内部类的单例属性提供给外部
3.具体实现
Kotlin实现
class UserManger private constructor(){
private object MyHolder {
val holder = UserManger()
}
companion object{
val instance :UserManger = MyHolder.holder
}
}
Java实现
public class FileManager {
private FileManager(){ }
private static class MyHolder{
private static final FileManager instance = new FileManager();
}
public static FileManager getInstance(){
return MyHolder.instance;
}
}
枚举类
1.解释
枚举中的各个枚举项都是通过static代码块来定义和初始化的,他们会在类被加载时完成初始化,而Java的类加载由JVM
保证线程安全。
2.实现逻辑
- 每个实例都登记到一个地方,使用唯一的标识获取单例
- 枚举的实例创建是由类加载机制来保证的,而类加载机制是线程安全的
3.具体实现
Kotlin实现
enum class EnumNewSingleton {
INSTANCE
}
Java实现
public enum EnumSingleton {
INSTANCE;
}