Jak utworzyć klasę Singleton w Kotlinie?

Jak utworzyć klasę Singleton w Kotlinie?

W Android App, dla obiektu, który jest wymagany do utworzenia tylko raz i używać wszędzie, używamy Singleton Pattern. Singleton Pattern jest wzorcem projektowym oprogramowania, który ogranicza instancję klasy do tylko „jednej” instancji. Tak więc, aby zaimplementować wzorzec Singleton w naszym projekcie lub oprogramowaniu, tworzymy klasę singleton. W tym blogu, dowiemy się, jak zrobić klasę singleton w Kotlinie? Więc, zaczynajmy.

Klasa singleton

Klasa singleton jest klasą, która jest zdefiniowana w taki sposób, że tylko jedna instancja klasy może być utworzona i używana wszędzie.

Jest używany, gdy potrzebujemy tylko jednej instancji klasy jak NetworkService, DatabaseService, itp.

Generalnie, jest to zrobione, ponieważ zajmuje zasoby systemu, aby utworzyć te obiekty ponownie i ponownie. Więc lepiej jest tworzyć tylko raz i używać ponownie tego samego obiektu.

Właściwości klasy singleton

Następujące są właściwości typowej klasy singleton:

  1. Tylko jedna instancja: Klasa singleton ma tylko jedną instancję i odbywa się to poprzez dostarczenie instancji klasy, wewnątrz klasy. Należy również uniemożliwić klasom zewnętrznym i podklasom tworzenie instancji.
  2. Globalnie dostępne: Instancja klasy singleton powinna być globalnie dostępna, aby każda klasa mogła z niej korzystać.

Reguły tworzenia klasy Singleton

Aby utworzyć klasę Singleton, należy przestrzegać następujących reguł:

  1. Prywatny konstruktor
  2. Statystyczna referencja swojej klasy
  3. Jedna statyczna metoda
  4. Globalnie dostępna referencja obiektu
  5. Skonsekwencja w wielu wątkach

Przykład Singletona

Poniżej przedstawiono przykład klasy Singleton w 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; }}

Podczas tworzenia instancji, aby zapewnić brak ingerencji wątków, używamy słowa kluczowego synchronized.

Spójrzmy na kod Kotlina dla tego samego. Poniżej znajduje się kod Kotlina dla klasy Singleton:

object Singleton

Ok, co zrobić po tym?

Nic! Czy ty sobie żartujesz? Nie, to jest kod do użycia klasy Singleton w Kotlinie. Bardzo proste? Nie martw się, spójrzmy na wyjaśnienie.

W Kotlinie, musimy użyć słowa kluczowego object, aby użyć klasy Singleton. Klasa obiektowa może mieć funkcje, właściwości i metodę init. Metoda konstruktora nie jest dozwolona w obiekcie, więc możemy użyć metody init, jeśli wymagana jest jakaś inicjalizacja i obiekt może być zdefiniowany wewnątrz klasy. Obiekt zostaje zainicjowany, gdy jest używany po raz pierwszy.

Miejmy przykład klasy Singleton w 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() }}

Tutaj, w powyższym przykładzie, mamy jedną funkcję o nazwie printVarName() i jedną właściwość o nazwie „variableName”. Kiedy klasa A jest instancjonowana, wtedy zmiany mogą być odzwierciedlone w klasie obiektu. Tak więc, wyjście z powyższego kodu będzie:

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

Obiekt rozszerzający klasę

Możesz użyć obiektu w Kotlinie, aby rozszerzyć jakąś klasę lub zaimplementować jakiś interfejs, tak jak normalna klasa. Przykładem niech będzie:

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 wyjście powyższego kodu będzie:

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

Więc, możesz używać klasy obiektów tak jak normalnej klasy w większości przypadków.

Learn System Design for your next Interview from here.

Singleton class with Argument in Kotlin

We wcześniejszej części bloga, dowiedzieliśmy się, że nie możemy mieć konstruktorów w klasie singleton. Aby coś zainicjalizować, możemy to zrobić za pomocą init w klasie singleton. Ale co jeśli potrzebujemy przekazać jakiś argument do inicjalizacji, tak jak w sparametryzowanych konstruktorach? Ponieważ nie możemy tutaj użyć konstruktorów. Więc, musimy znaleźć jakiś inny sposób na zrobienie tego samego.

Jeśli szczególnie mówimy o Androidzie, wiemy, że w Androidzie generalnie musimy przekazać instancję kontekstu do bloku init klasy singleton. Można to zrobić za pomocą wczesnej inicjalizacji i leniwej inicjalizacji. W przypadku wczesnej inicjalizacji, wszystkie komponenty są inicjalizowane w Application.onCreate() przy użyciu funkcji init(). Powoduje to jednak spowolnienie uruchamiania aplikacji poprzez blokowanie głównego wątku. Tak więc, generalnie zaleca się używanie leniwej inicjalizacji. W leniwej inicjalizacji, używamy kontekstu jako argumentu do funkcji zwracającej instancję singletonu. Możemy to osiągnąć poprzez użycie klasy SingletonHolder. Ponadto, aby uczynić go bezpiecznym dla wątków, musimy mieć sposób na synchronizację i podwójnie sprawdzane blokowanie.

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

Powyższy kod jest najbardziej wydajnym kodem dla podwójnie sprawdzanego systemu blokowania i kod jest w jakiś sposób podobny do funkcji lazy() w Kotlinie i dlatego jest nazywany leniwą inicjalizacją. Tak więc, gdy chcesz mieć klasę singleton z argumentami, możesz użyć klasy SingletonHolder.

Tutaj, w powyższym kodzie, w miejsce funkcji Creator, która jest przekazywana jako argument do SingletonHolder, niestandardowa lambda może być również zadeklarowana inline lub możemy przekazać referencję do prywatnego konstruktora klasy singleton. Więc, kod będzie:

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

Teraz, singleton może być łatwo wywołany i zainicjalizowany przez napisanie poniższego kodu i jest to zarówno leniwe jak i bezpieczne dla wątków 🙂

YourManager.getInstance(context).doSomething()

To jest to dla Singleton blog. Mam nadzieję, że podoba Ci się ten blog. Możesz również odnieść się do strony internetowej Kotlin. Aby dowiedzieć się więcej o niektórych z fajnych tematów Android, można odwiedzić naszą stronę internetową blogów i może dołączyć do naszej podróży nauki.

Keep Learning 🙂

Team MindOrks!

Dodaj komentarz