Moosphan / Android-Daily-Interview

:pushpin:每工作日更新一道 Android 面试题,小聚成河,大聚成江,共勉之~

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

2019-07-12:Kotlin中实现单例的几种常见方式?

Moosphan opened this issue · comments

2019-07-12:Kotlin中实现单例的几种常见方式?

by lazy 加上同步关键字sy

不会kotlin
打卡
告辞

  • 饿汉式:
object StateManagementHelper {

    fun init() {
        //do some initialization works

    }
}
  • 懒汉式:
class StateManagementHelper private constructor(){
    
    companion object {
        private var instance: StateManagementHelper? = null 
            @Synchronized get() {
            if (field == null)
                field = StateManagementHelper()
            return field
        }
    }

    fun init() {
        //do some initialization works
        
    }
}
  • 双重检测:
class StateManagementHelper private constructor(){

    companion object {
        val instance: StateManagementHelper 
                by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { StateManagementHelper() }
    }

    fun init() {
        //do some initialization works

    }
}
  • 静态内部类:
class StateManagementHelper private constructor(){

    companion object {
       val INSTANCE = StateHelperHolder.holder
    }
    
    private object StateHelperHolder {
        val holder = StateManagementHelper()
    }

    fun init() {
        //do some initialization works
        
    }
}

object

companion object {
val instance: SyncData by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {SyncData() }
}

  • 饿汉式:
object StateManagementHelper {

    fun init() {
        //do some initialization works

    }
}
  • 懒汉式:
class StateManagementHelper private constructor(){
    
    companion object {
        private var instance: StateManagementHelper? = null 
            @Synchronized get() {
            if (field == null)
                field = StateManagementHelper()
            return field
        }
    }

    fun init() {
        //do some initialization works
        
    }
}
  • 双重检测:
class StateManagementHelper private constructor(){

    companion object {
        val instance: StateManagementHelper 
                by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { StateManagementHelper() }
    }

    fun init() {
        //do some initialization works

    }
}
  • 静态内部类:
class StateManagementHelper private constructor(){

    companion object {
       val INSTANCE = StateHelperHolder.holder
    }
    
    private object StateHelperHolder {
        val holder = StateManagementHelper()
    }

    fun init() {
        //do some initialization works
        
    }
}

这个回答比较全,
关于双重校验,kotlin用了委托机制的延迟属性: lazy(「lambda表达式」),这一点真的爽歪歪
其他的与java没有什么区别

不会用枚举?

:octocat: From gitme iOS

  • 饿汉式:
object StateManagementHelper {

    fun init() {
        //do some initialization works

    }
}
  • 懒汉式:
class StateManagementHelper private constructor(){
    
    companion object {
        private var instance: StateManagementHelper? = null 
            @Synchronized get() {
            if (field == null)
                field = StateManagementHelper()
            return field
        }
    }

    fun init() {
        //do some initialization works
        
    }
}
  • 双重检测:
class StateManagementHelper private constructor(){

    companion object {
        val instance: StateManagementHelper 
                by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { StateManagementHelper() }
    }

    fun init() {
        //do some initialization works

    }
}
  • 静态内部类:
class StateManagementHelper private constructor(){

    companion object {
       val INSTANCE = StateHelperHolder.holder
    }
    
    private object StateHelperHolder {
        val holder = StateManagementHelper()
    }

    fun init() {
        //do some initialization works
        
    }
}

双重检查锁,没有必要写mode = LazyThreadSafetyMode.SYNCHRONIZED,因为这是默认的方式,当然了,写上也不会有错

  • 饿汉式:
object StateManagementHelper {

    fun init() {
        //do some initialization works

    }
}
  • 懒汉式:
class StateManagementHelper private constructor(){
    
    companion object {
        private var instance: StateManagementHelper? = null 
            @Synchronized get() {
            if (field == null)
                field = StateManagementHelper()
            return field
        }
    }

    fun init() {
        //do some initialization works
        
    }
}
  • 双重检测:
class StateManagementHelper private constructor(){

    companion object {
        val instance: StateManagementHelper 
                by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { StateManagementHelper() }
    }

    fun init() {
        //do some initialization works

    }
}
  • 静态内部类:
class StateManagementHelper private constructor(){

    companion object {
       val INSTANCE = StateHelperHolder.holder
    }
    
    private object StateHelperHolder {
        val holder = StateManagementHelper()
    }

    fun init() {
        //do some initialization works
        
    }
}

我有一个疑问,在懒汉式的写法里,在半生对象里的访问修饰符是 private 外面能访问到吗?

class StateManagementHelper private constructor(){
    
    companion object {
//这里是私有的啊????
        private var instance: StateManagementHelper? = null 
            @Synchronized get() {
            if (field == null)
                field = StateManagementHelper()
            return field
        }
    }

    fun init() {
        //do some initialization works
        
    }
}

饿汉式

object Singleton

线程安全的懒汉式

class Singleton private constructor() {

    companion object {
        private var instance: Singleton? = null
            get() {
                if (field == null) field = Singleton()
                return field
            }

        @Synchronized
        fun instance(): Singleton {
            return instance!!
        }
    }
}

双重校验锁式

/**
 * 双重校验锁式
 * Lazy是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托
 * 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果,后续调用 get() 只是返回记录的结果
 * Lazy默认的线程模式就是 LazyThreadSafetyMode.SYNCHRONIZED 内部默认双重校验锁
 * # Lazy内部实现
 * ```
 * public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
 *      when (mode) {
 *        LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
 *        LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
 *        LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
 *      }
 * ```
 * ### Lazy接口
 * ```
 * public interface Lazy<out T> {
 *     //当前实例化对象,一旦实例化后,该对象不会再改变
 *     public val value: T
 *     //返回true表示,已经延迟实例化过了,false 表示,没有被实例化,
 *     //一旦方法返回true,该方法会一直返回true,且不会再继续实例化
 *     public fun isInitialized(): Boolean
 * }
 * ```
 * ### SynchronizedLazyImpl
 * ```
 * private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
 *     private var initializer: (() -> T)? = initializer
 *     @Volatile private var _value: Any? = UNINITIALIZED_VALUE
 *     // final field is required to enable safe publication of constructed instance
 *     private val lock = lock ?: this
 *
 *     override val value: T
 *         get() {
 *             val _v1 = _value
 *             //判断是否已经初始化过,如果初始化过直接返回,不在调用高级函数内部逻辑
 *             if (_v1 !== UNINITIALIZED_VALUE) {
 *                 @Suppress("UNCHECKED_CAST")
 *                 return _v1 as T
 *             }
 *
 *             return synchronized(lock) {
 *                 val _v2 = _value
 *                 if (_v2 !== UNINITIALIZED_VALUE) {
 *                     @Suppress("UNCHECKED_CAST") (_v2 as T)
 *                 }
 *                 else {
 *                     //调用高级函数获取其返回值
 *                     val typedValue = initializer!!()
 *                     //将返回值赋值给_value,用于下次判断时,直接返回高级函数的返回值
 *                     _value = typedValue
 *                     initializer = null
 *                     typedValue
 *                 }
 *             }
 *         }
 *         //省略部分代码
 * }
 * ```
 */
class Singleton private constructor() {
    companion object {
        val instance by lazy { Singleton() }
    }
}

静态内部类式

class Singleton private constructor() {
    companion object {
        val instance = SingletonHolder.holder
    }

    private object SingletonHolder {
        val holder = Singleton()
    }
}

枚举式

enum class Singleton {
    INSTANCE;
}

楼上所有的懒汉式 对象变量都声明为私有的了,私有变量外界如何获取?

楼上所有的懒汉式 对象变量都声明为私有的了,私有变量外界如何获取?

class Singleton private constructor() {
    companion object {
        private var INSTANCE: Singleton? = null
            get() {
                if (field == null) field = Singleton()
                return field
            }

        @Synchronized fun getInstance() = INSTANCE!!
    }

    fun foo() {}
}