Jak vytvořit singletonovou třídu v jazyce Kotlin?

Jak vytvořit singletonovou třídu v jazyce Kotlin?

V aplikaci Android pro objekt, který má být vytvořen pouze jednou a použit všude, používáme vzor Singleton. Vzor Singleton je návrhový vzor softwaru, který omezuje instanci třídy pouze na „jednu“ instanci. Chceme-li tedy v našem projektu nebo softwaru implementovat vzor Singleton, vytvoříme třídu Singleton. V tomto blogu se dozvíme, jak vytvořit singletonovou třídu v jazyce Kotlin? Začněme tedy.

Třída singleton

Třída singleton je třída, která je definována tak, že lze vytvořit pouze jednu instanci této třídy a tu všude používat.

Používá se tam, kde potřebujeme pouze jednu instanci třídy, například NetworkService, DatabaseService atd.

Všeobecně se to dělá proto, že vytváření těchto objektů znovu a znovu zabírá prostředky systému. Proto je lepší vytvořit pouze jednou a znovu a znovu používat stejný objekt.

Vlastnosti singletonové třídy

Následující vlastnosti typické singletonové třídy:

  1. Pouze jedna instance: Třída singleton má pouze jednu instanci, a to tak, že v rámci třídy poskytuje instanci třídy. Také vnějším třídám a podtřídám by mělo být znemožněno vytvořit instanci.
  2. Globálně přístupná: Instance singletonové třídy by měla být globálně přístupná, aby ji mohla používat každá třída.

Pravidla pro vytvoření třídy Singleton

Při vytváření třídy Singleton se postupuje podle následujících pravidel:

  1. Soukromý konstruktor
  2. Statický odkaz na svou třídu
  3. Jedna statická metoda
  4. Globálně přístupný odkaz na objekt
  5. Konzistence ve více vláknech

Příklad třídy Singleton

Následuje příklad třídy Singleton v Javě:

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

Při vytváření instance, abychom zajistili, že nedojde k rušení vláken, použijeme klíčové slovo synchronized.

Podívejme se na stejný kód v jazyce Kotlin. Níže je uveden kód jazyka Kotlin pro třídu Singleton:

object Singleton

Ok, co dělat potom?

Nic! Děláte si legraci? Ne, to je kód pro použití třídy Singleton v jazyce Kotlin. Velmi jednoduché? Nebojte se, podívejme se na vysvětlení.

V jazyce Kotlin musíme pro použití třídy Singleton použít klíčové slovo object. Třída objekt může mít funkce, vlastnosti a metodu init. Metoda konstruktoru není v objektu povolena, takže můžeme použít metodu init, pokud je vyžadována nějaká inicializace a objekt může být definován uvnitř třídy. Objekt se instancuje při prvním použití.

Uveďme si příklad třídy Singleton v jazyce 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() }}

Ve výše uvedeném příkladu máme jednu funkci s názvem printVarName() a jednu vlastnost s názvem „variableName“. Když je třída A instancována, pak se změny mohou projevit v objektu třídy. Výstupem výše uvedeného kódu tedy bude:

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

Objekt rozšiřující třídu

Objekt můžete v jazyce Kotlin použít k rozšíření nějaké třídy nebo k implementaci nějakého rozhraní stejně jako běžnou třídu. Uveďme si příklad téhož:

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 výstup výše uvedeného kódu bude:

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

Ve většině případů tedy můžete objektovou třídu používat stejně jako normální třídu.

Zde se naučíte navrhovat systém pro svůj další rozhovor.

Třída singleton s argumentem v Kotlinu

V předchozí části blogu jsme se dozvěděli, že v třídě singleton nemůžeme mít konstruktory. Pokud chceme něco inicializovat, můžeme tak učinit pomocí init v singletonové třídě. Ale co když potřebujeme pro inicializaci předat nějaký argument stejně jako u parametrizovaných konstruktorů? Protože zde nemůžeme použít konstruktory. Musíme tedy najít nějaký jiný způsob, jak totéž provést.

Pokud se budeme bavit zejména o Androidu, víme, že v Androidu obecně potřebujeme do bloku init singletonu předat instanci kontextu. To lze provést pomocí Early initialization a Lazy initialization. Při časné inicializaci jsou všechny komponenty inicializovány v Application.onCreate() pomocí funkcí init(). To však vede ke zpomalení spouštění aplikace zablokováním hlavního vlákna. Proto se obecně doporučuje používat způsob líné inicializace. Při líné inicializaci používáme kontext jako argument funkce vracející instanci singletonu. Toho můžeme dosáhnout pomocí třídy SingletonHolder. Také, aby to bylo bezpečné pro vlákna, musíme mít způsob synchronizace a dvojitě kontrolovaného zamykání.

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

Výše uvedený kód je nejefektivnějším kódem pro systém dvojitě kontrolovaného zamykání a kód je nějakým způsobem podobný funkci lazy() v Kotlinu, a proto se nazývá líná inicializace. Kdykoli tedy chcete mít singletonovou třídu s argumenty, pak můžete použít třídu SingletonHolder.

Ve výše uvedeném kódu můžeme místo funkce creator, která se předává jako argument třídě SingletonHolder, deklarovat také vlastní lambdu inline nebo můžeme předat odkaz na soukromý konstruktor singletonové třídy. Kód tedy bude vypadat takto:

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

Nyní lze singleton snadno vyvolat a inicializovat zapsáním níže uvedeného kódu a je to líné i bezpečné pro vlákna 🙂

YourManager.getInstance(context).doSomething()

To je vše pro blog o singletonech. Doufám, že se vám tento blog líbil. Můžete se také podívat na webové stránky Kotlinu. Chcete-li se dozvědět více o některých zajímavých tématech systému Android, můžete navštívit naše blogové stránky a můžete se připojit k naší cestě za poznáním.

Keep Learning 🙂

Team MindOrks!

Napsat komentář