Hogyan hozzunk létre egy Singleton osztályt Kotlinban?

Hogyan hozzunk létre egy singleton osztályt Kotlinban?

Az Android alkalmazásban egy olyan objektumhoz, amelyet csak egyszer kell létrehozni és mindenhol használni, a Singleton mintát használjuk. A Singleton Pattern egy olyan szoftvertervezési minta, amely az osztály példányosítását csak “egy” példányra korlátozza. Tehát, hogy a Singleton mintát a projektünkben vagy szoftverünkben megvalósítsuk, létrehozunk egy singleton osztályt. Ebben a blogban megtanuljuk, hogyan készítsünk egy singleton osztályt Kotlinban? Tehát kezdjük el.

Singleton osztály

A singleton osztály egy olyan osztály, amelyet úgy definiálunk, hogy az osztályból csak egy példányt hozhatunk létre és mindenhol használhatjuk.

Ezt ott használjuk, ahol az osztályból csak egy példányra van szükségünk, mint például NetworkService, DatabaseService, stb.

Általában azért csináljuk, mert a rendszer erőforrását veszi igénybe, hogy ezeket az objektumokat újra és újra létrehozzuk. Ezért jobb, ha csak egyszer hozzuk létre, és újra és újra ugyanazt az objektumot használjuk.

A singleton osztály tulajdonságai

A következők a tipikus singleton osztály tulajdonságai:

  1. Csak egy példány: A singleton osztálynak csak egy példánya van, és ezt úgy érjük el, hogy az osztályon belül az osztály egy példányát adjuk meg. Továbbá meg kell akadályozni, hogy a külső osztályok és alosztályok létrehozzák a példányt.
  2. Globálisan elérhető: A singleton osztály példányának globálisan elérhetőnek kell lennie, hogy minden osztály használhassa.

Singleton osztály készítésének szabályai

A Singleton osztály készítéséhez a következő szabályokat kell követni:

  1. Egy privát konstruktor
  2. Egy statikus hivatkozás az osztályára
  3. Egy statikus metódus
  4. Globálisan elérhető objektumreferencia
  5. Konzisztencia több szálon keresztül

Singleton példa

A következő a Singleton osztály példája java-ban:

public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }}

A példány létrehozásakor a szinkronizált kulcsszót használjuk, hogy biztosítsuk a szálak közötti interferencia elkerülését.

Nézzük meg ugyanehhez a Kotlin kódot. Az alábbiakban a Singleton osztály Kotlin kódja:

object Singleton

Oké, mi a teendő ezután?

Semmi! Most viccelsz? Nem, ez a Singleton osztály használatának kódja Kotlinban. Nagyon egyszerű? Ne aggódj, nézzük a magyarázatot.

A Kotlinban a Singleton osztály használatához az object kulcsszót kell használnunk. Az objektum osztály rendelkezhet függvényekkel, tulajdonságokkal és az init metódussal. A konstruktor metódus nem megengedett egy objektumban, így használhatjuk az init metódust, ha valamilyen inicializálásra van szükség, és az objektum egy osztályon belül definiálható. Az objektum akkor instanciálódik, amikor először használjuk.

Lássunk egy példát a Singleton osztályra Kotlinban.

object Singleton{ init { println("Singleton class invoked.") } var variableName = "I am Var" fun printVarName(){ println(variableName) }}fun main(args: Array<String>) { Singleton.printVarName() Singleton.variableName = "New Name" var a = A()}class A { init { println("Class init method. Singleton variableName property : ${Singleton.variableName}") Singleton.printVarName() }}

Itt, a fenti példában van egy printVarName() nevű függvényünk és egy “variableName” nevű tulajdonságunk. Amikor egy osztály instanciálódik, akkor a változások tükröződhetnek az objektum osztályban. Tehát a fenti kód kimenete a következő lesz:

Singleton class invoked.I am VarClass init method. Singleton variableName property : New NameNew Name

Object extending a class

A Kotlinban egy objektumot használhatunk valamilyen osztály kiterjesztésére vagy valamilyen interfész megvalósítására, akárcsak egy normál osztály esetében. Lássunk egy példát ugyanerre:

fun main(args: Array<String>) { var a = A() Singleton.printVarName()}open class A { open fun printVarName() { print("I am in class printVarName") } init { println("I am in init of A") }}object Singleton : A() { init { println("Singleton class invoked.") } var variableName = "I am Var" override fun printVarName() { println(variableName) }}

A fenti kód kimenete pedig:

I am in init of AI am in init of ASingleton class invoked.I am var

A legtöbb esetben tehát ugyanúgy használhatjuk az objektum osztályt, mint egy normál osztályt.

Tanulj rendszertervezést a következő interjúdhoz innen.

Singleton osztály argumentummal Kotlinban

A blog korábbi részében megtanultuk, hogy egy singleton osztályban nem lehet konstruktorunk. Ahhoz, hogy valamit inicializáljunk, a singleton osztályban az init használatával tehetjük ezt meg. De mi van akkor, ha az inicializáláshoz valamilyen argumentumot kell átadni, mint a paraméterezett konstruktorokban? Mivel itt nem használhatunk konstruktorokat. Tehát valami más módot kell találnunk ugyanerre.

Ha kifejezetten az Androidról beszélünk, akkor tudjuk, hogy az Androidban általában egy kontextuspéldányt kell átadnunk egy singleton init blokkjának. Ezt megtehetjük az Early initialization és a Lazy initialization segítségével. A korai inicializálás során az összes komponens inicializálása az Application.onCreate() függvények segítségével történik. Ez azonban az alkalmazás indításának lelassulását eredményezi a főszál blokkolásával. Ezért általában a lusta inicializálási mód használata javasolt. A lusta inicializálás során a kontextust egy olyan függvény argumentumaként használjuk, amely visszaadja a singleton példányát. Ezt egy SingletonHolder osztály használatával érhetjük el. Továbbá, hogy szálbiztos legyen, szükségünk van a szinkronizálás és a kettős ellenőrzésű zárás módjára.

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 checkInstance = instance if (checkInstance != null) { return checkInstance } return synchronized(this) { val checkInstanceAgain = instance if (checkInstanceAgain != null) { checkInstanceAgain } else { val created = creator!!(arg) instance = created creator = null created } } }}

A fenti kód a leghatékonyabb kód a kettős ellenőrzésű zárási rendszerhez, és a kód valahogy hasonlít a Kotlin lazy() függvényéhez, ezért is hívják lazy inicializálásnak. Tehát, amikor egy singleton osztályt akarunk érvekkel, akkor használhatjuk a SingletonHolder osztályt.

A fenti kódban a SingletonHolder-nek argumentumként átadott creator függvény helyett inline deklarálhatunk egy saját lambdát is, vagy átadhatunk egy hivatkozást a singleton osztály privát konstruktorára. A kód tehát a következő lesz:

class YourManager private constructor(context: Context) { init { // do something with context } companion object : SingletonHolder<YourManager, Context>(::YourManager)}

Az alábbi kód megírásával most már egyszerűen meghívható és inicializálható a singleton, és ez lusta, valamint szálbiztos 🙂

YourManager.getInstance(context).doSomething()

Ez volt a Singleton blog. Remélem, tetszik ez a blog. A Kotlin weboldalát is megtekintheti. Ha többet szeretne megtudni az Android néhány menő témájáról, akkor látogasson el a blogos weboldalunkra, és csatlakozhat a tanulási utazásunkhoz.

Keep Learning 🙂

Team MindOrks!

Szólj hozzá!