1. Singleton chino hambriento
Kotlin admite singletons a nivel gramatical, es decir, la palabra clave de objeto, que es mucho más simple que el código de plantilla de singletons de Java:
object WorkSingleton
Después de la descompilación, encontrará que object
en realidad es un 一个
singleton basado en estática del hombre hambriento, que es algo seguro para subprocesos. La desventaja es que la carga diferida no se puede lograr:
public final class WorkSingleton {
public static final WorkSingleton INSTANCE;
static {
WorkSingleton var0 = new WorkSingleton();
INSTANCE = var0;
}
}
2. Singleton perezoso
Y el uso de objetos asociados by lazy
también se puede implementar en una única realización, se puede implementar la fórmula Singleton segura para subprocesos perezosos
class WorkSingleton private constructor() {
companion object {
//LazyThreadSafetyMode.SYNCHRONIZED可以省略
val INSTANCE1 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
WorkSingleton() }
}
}
En un entorno no multiproceso, sí mode = LazyThreadSafetyMode.NONE
, es un singleton seguro para subprocesos para mejorar el rendimiento
3. Singleton con parámetros
A veces desea pasar parámetros cuando se inicializa el singleton, por ejemplo
Singleton.getInstance(context).doSome()
Se puede lograr mediante la herencia de objetos complementarios:
class WorkSingleton private constructor(context: Context) {
init {
// Init using context argument
}
companion object : SingletonHolder<WorkSingleton, Context>(::WorkSingleton)
}
open class SingletonHolder<out T : Any, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile
private var instance: T? = null
fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
Es muy similar al mecanismo de bloqueo de doble verificación en Java. SingletonHolder
Si la clase se ha inicializado, volverá directamente. Si no se ha inicializado, entrará en el bloque de código sincronizado para crear un objeto.
A través de Kotlin, el objeto complementario como una subclase realiza la función equivalente a la herencia estática. Por lo tanto, usamos SingletonHolder como la clase base del objeto complementario singleton para facilitar la reutilización en la clase singleton. Para el modo singleton que necesita pasar parámetros, solo Debe heredar el objeto complementario de la clase singleton SingletonHolder
y luego especificar la clase singleton y los tipos de parámetros mediante genéricos:
class FileSingleton private constructor(path: String) {
companion object : SingletonHolder<FileSingleton, String>(::FileSingleton)
}