Hur man skapar en singletonklass i Kotlin?

Hur man skapar en singletonklass i Kotlin?

I Android-appen använder vi singletonmönstret för ett objekt som bara ska skapas en gång och användas överallt. Singletonmönstret är ett mjukvarudesignmönster som begränsar instantieringen av klassen till endast ”en” instans. För att implementera singletonmönstret i vårt projekt eller vår programvara skapar vi en singletonklass. I den här bloggen kommer vi att lära oss hur man gör en singletonklass i Kotlin? Så låt oss börja.

Singletonklass

En singletonklass är en klass som definieras på ett sådant sätt att endast en instans av klassen kan skapas och användas överallt.

Den används när vi bara behöver en instans av klassen, som till exempel NetworkService, DatabaseService, etc.

Generellt sett görs det för att det tar resurserna i systemet att skapa dessa objekt om och om igen. Så det är bättre att bara skapa en gång och använda samma objekt om och om igen.

Egenskaper hos en singletonklass

Följande är egenskaperna hos en typisk singletonklass:

  1. Endast en instans: Singletonklassen har endast en instans och detta görs genom att tillhandahålla en instans av klassen, inom klassen. Dessutom ska yttre klasser och underklasser förhindras att skapa instansen.
  2. Globalt tillgänglig: Instansen av singletonklassen bör vara globalt tillgänglig så att varje klass kan använda den.

Regler för att göra en singletonklass

Följande regler följs för att göra en singletonklass:

  1. En privat konstruktör
  2. En statisk referens till sin klass
  3. En statisk metod
  4. Globalt tillgänglig objektreferens
  5. Konsistens över flera trådar

Singleton Exempel

Följande är exemplet på Singleton-klass i java:

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; }}

När vi skapar instansen för att säkerställa att det inte finns någon trådinterferens använder vi nyckelordet synchronized.

Låt oss titta på Kotlin-koden för samma sak. Nedan följer Kotlin-koden för Singleton-klassen:

object Singleton

Okej, vad ska vi göra efter detta?

Inget! Skojar du? Nej, det är koden för att använda Singleton-klassen i Kotlin. Mycket enkelt? Oroa dig inte, låt oss titta på förklaringen.

I Kotlin måste vi använda nyckelordet object för att använda Singleton-klassen. Objektklassen kan ha funktioner, egenskaper och init-metoden. Konstruktörsmetoden är inte tillåten i ett objekt så vi kan använda init-metoden om viss initialisering krävs och objektet kan definieras inuti en klass. Objektet blir instansierat när det används för första gången.

Låt oss ta ett exempel på singletonklassen i Kotlin.

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() }}

Här, i exemplet ovan, har vi en funktion som heter printVarName() och en egenskap som heter ”variableName”. När en klass instansieras kan ändringar återspeglas i objektklassen. Så resultatet av ovanstående kod blir:

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

Objekt som förlänger en klass

Du kan använda ett objekt i Kotlin för att förlänga en klass eller implementera ett gränssnitt precis som en vanlig klass. Låt oss ta ett exempel på samma sak:

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) }}

Och resultatet av ovanstående kod blir:

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

Så, du kan använda en objektklass precis som en vanlig klass i de flesta fall.

Lär dig systemdesign för din nästa intervju härifrån.

Singletonklass med argument i Kotlin

I den tidigare delen av bloggen lärde vi oss att vi inte kan ha konstruktörer i en singletonklass. För att initialisera något kan vi göra det genom att använda init i singletonklassen. Men vad händer om man behöver lämna över något argument för initialisering precis som i parametrerade konstruktörer? Eftersom vi inte kan använda konstruktörer här. Så vi måste hitta något annat sätt att göra detsamma.

Om vi särskilt pratar om Android vet vi att i Android behöver vi i allmänhet lämna över en kontextinstans till init-blocket för en singleton. Detta kan göras med hjälp av Early initialization och Lazy initialization. Vid tidig initialisering initialiseras alla komponenter i Application.onCreate() med hjälp av funktionerna init(). Men detta resulterar i att starten av applikationen blir långsammare genom att huvudtråden blockeras. Så det rekommenderas i allmänhet att använda det lata initialiseringssättet. Vid lat initialisering använder vi kontexten som ett argument till en funktion som returnerar instansen av singletonen. Vi kan uppnå detta genom att använda en SingletonHolder-klass. För att göra det trådsäkert måste vi också ha ett sätt för synkronisering och dubbelkontrollerad låsning.

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 } } }}

Ovanstående kod är den mest effektiva koden för dubbelkontrollerat låssystem och koden liknar på något sätt lazy()-funktionen i Kotlin och det är därför den kallas för lazy initialization. Så när du vill ha en singletonklass med argument kan du använda klassen SingletonHolder.

Här, i ovanstående kod, i stället för creator-funktionen som skickas som ett argument till SingletonHolder, kan en anpassad lambda också deklareras inline eller så kan vi skicka en referens till den privata konstruktören för singletonklassen. Så koden blir:

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

Nu kan singleton enkelt åberopas och initialiseras genom att skriva nedanstående kod och detta är både lat och trådsäkert 🙂

YourManager.getInstance(context).doSomething()

Det var allt för Singleton-bloggen. Hoppas du gillar den här bloggen. Du kan också hänvisa till Kotlins webbplats. Om du vill lära dig mer om några av de häftiga ämnena inom Android kan du besöka vår bloggwebbplats och kan följa med på vår resa för att lära dig.

Keep Learning 🙂

Team MindOrks!

Lämna en kommentar