单例模式(Java和kotlin版)

饿汉式

Java版:

public class SingletonDemo {
    private static SingletonDemo instance=new SingletonDemo();
    private SingletonDemo(){

    }
    public static SingletonDemo getInstance(){
        return instance;
    }
}

Kotlin版:

Kotlin中类没有静态方法,如果需要一个无需类实例,但是需要访问类内部函数的类,可以将这个类声明位为object,代码如下:

object SingletonDemo

懒汉式

线程安全的懒汉式

public class SafeSingletonDemo {
    private static SafeSingletonDemo instance;

    private SafeSingletonDemo() { }

    //使用同步锁解决线程安全问题
    public static synchronized SafeSingletonDemo getInstance() {
        if (instance == null) {
            instance = new SafeSingletonDemo();
        }
        return instance;
    }
}

Kotlin版:
在Kotlin中,使用同步锁需要添加 @Synchronized

class SafeSingletonKtDemo {
    companion object {
        private var instance: SafeSingletonKtDemo? = null
            get() {
                if (field == null) {
                    field = SafeSingletonKtDemo()
                }
                return field
            }
        
        @Synchronized
        fun get(): SafeSingletonKtDemo {
            return instance!!
        }
    }
}

双重检查模式

  1. 构造方法私有化,防止外部调用。
  2. synchronized同步锁,防止多线程同时创建问题。
  3. 使用double check,第一个非空判断解决使用同步锁带来的效率问题,仅当未创建实例时进去synchronized代码段,第二个非空判断解决创建多个实例的问题。
  4. 因为instance = new Single()为非原子操作,而Java使用了指令重排,故多线程时可能出现实例已经创建但未初始化的情况。使用volatile关键字禁用指令重排,可解决问题。
    Java版代码:
public class LazySingletonDemo {
    //validate关键字禁用指令重排,保证了对象的可见性
    private static volatile LazySingletonDemo INSTANCE;

    //将构造器私有化防止直接new生成对象
    private LazySingletonDemo() { }

    public static LazySingletonDemo getInstance() {
        //双重检查机制,第一次判空,解决同步锁效率问题,已经创建过则直接返回实例
        if (INSTANCE == null) {
            synchronized (LazySingletonDemo.class) {
                //第二次非空判断,解决创建多个实例的问题
                if (INSTANCE == null) {
                    INSTANCE = new LazySingletonDemo();
                }
            }
        }

        return INSTANCE;
    }
}

Kotlin版:
Kotlin中借助懒加载属性实现,lazy是一种延迟属性,它接受一个lambda表达式并返回lazy实例,在第一次get()的时候执行lazy中的lambda表达式,同时记录下结果,在后续调用get()时直接返回结果

class LazySingletonKtDemo private constructor() {
    companion object {
        //lazy延迟属性,接受一个lambda表达式并返回lazy实例
        val instance: LazySingletonKtDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            LazySingletonKtDemo()
        }
    }
}

静态内部类模式

  1. 使用静态内部类,利用类加载器保证同步性,在内部类中完成实例的创建。因为是内部类,故仅在在外部类相应方法被调用时内部类才会被装载。
  2. 内部类为饿汉式,外部类为懒汉式,将两者优势结合,十分巧妙。
    Java版:
public class SingletonDemo {
    private SingletonDemo() { }

    private static class SingletonHelper {
        private static SingletonDemo instance = new SingletonDemo();
    }

    public static SingletonDemo getInstance() {
        return SingletonHelper.instance;
    }
}

Kotlin版:

class SingletonDemo private constructor() {
    companion object {
        fun get(): SingletonDemo {
            return Helper.instance
        }
    }

    private object Helper {
        val instance = SingletonDemo()
    }
}

总结

可以看到使用Kotlin使得代码更加简洁,对于简单的单例模式更是一行代码解决问题。加之今年Kotlin正式成为安卓首选语言,学习Kotlin已经是大势所趋了。

你可能感兴趣的:(单例模式(Java和kotlin版))