Como criar uma classe singleton em Kotlin?

Como criar uma classe singleton em Kotlin?

Na aplicação Android, para um objeto que é necessário ser criado apenas uma vez e usar em todos os lugares, usamos o Padrão Singleton. Singleton Pattern é um padrão de design de software que restringe a instanciação da classe a apenas “uma” instância. Assim, para implementar o padrão Singleton em nosso projeto ou software, nós fazemos uma classe singleton. Neste blog, vamos aprender como fazer uma classe singleton no Kotlin? Então, vamos começar.

Classe Singleton

Uma classe singleton é uma classe que é definida de tal forma que apenas uma instância da classe pode ser criada e usada em qualquer lugar.

É usada onde precisamos apenas de uma instância da classe como NetworkService, DatabaseService, etc.

Generalmente, ela é feita porque leva o recurso do sistema para criar esses objetos de novo e de novo. Então é melhor criar apenas uma vez e usar repetidamente o mesmo objeto.

Propriedades da Classe Singleton

Seguir são as propriedades de uma típica classe singleton:

  1. Apenas uma instância: A classe singleton tem apenas uma instância e isto é feito através do fornecimento de uma instância da classe, dentro da classe. Além disso, classes e subclasses externas devem ser evitadas para criar a instância.
  2. Globalmente acessível: A instância da classe singleton deve ser globalmente acessível para que cada classe possa utilizá-la.

Regras para fazer uma classe Singleton

As seguintes regras são seguidas para fazer uma classe Singleton:

  1. Um construtor privado
  2. Uma referência estática da sua classe
  3. Um método estático
  4. Uma referência de objeto acessível gloobalmente
  5. Consistência através de múltiplos fios

Exemplo Singleton

A seguir é o exemplo da classe Singleton em 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; }}

Ao criar a instância para garantir que não haja interferência de threads, usamos a palavra-chave sincronizada.

Vejamos o código do Kotlin para o mesmo. Abaixo está o código Kotlin para a classe Singleton:

object Singleton

Ok, o que fazer depois disto?

Nada! Você está brincando? Não, esse é o código para usar a classe Singleton em Kotlin. Muito simples? Não se preocupe, vamos ver a explicação.

Em Kotlin, precisamos usar a palavra-chave object para usar a classe Singleton. A classe objeto pode ter funções, propriedades, e o método init. O método construtor não é permitido em um objeto, então podemos usar o método init se alguma inicialização for necessária e o objeto puder ser definido dentro de uma classe. O objeto é instanciado quando é usado pela primeira vez.

Vamos ter um exemplo da classe Singleton em 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() }}

Aqui, no exemplo acima, estamos tendo uma função chamada printVarName() e uma propriedade chamada “variableName”. Quando uma classe é instanciada, então as alterações podem ser refletidas na classe objeto. Então, a saída do código acima será:

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

Objecto estendendo uma classe

Pode usar um objecto no Kotlin para estender alguma classe ou implementar alguma interface tal como uma classe normal. Vamos ter um exemplo do mesmo:

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

E a saída do código acima será:

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

Então, você pode usar a classe objeto como uma classe normal na maioria dos casos.

Aprenda o design do sistema para sua próxima entrevista daqui.

Classe Singleton com Argument em Kotlin

Na parte anterior do blog, aprendemos que não podemos ter construtores em uma classe singleton. Para inicializar algo, nós podemos fazer isso usando init na classe singleton. Mas e se você precisar passar algum argumento para inicialização como nos construtores parametrizados? Já que não podemos usar construtores aqui. Então, precisamos encontrar alguma outra forma de fazer o mesmo.

Se falamos particularmente do Android, sabemos que no Android geralmente precisamos passar uma instância de contexto para o bloco de init de um singleton. Isto pode ser feito usando Inicialização antecipada e Inicialização preguiçosa. Na inicialização antecipada, todos os componentes são inicializados no Application.onCreate() usando as funções init(). Mas isto resulta na desaceleração da inicialização da aplicação através do bloqueio da thread principal. Portanto, geralmente é aconselhável usar o modo de inicialização preguiçosa. Na inicialização preguiçosa, usamos o contexto como um argumento para uma função retornando a instância do singleton. Podemos conseguir isto usando uma classe SingletonHolder. Também, para torná-la thread-safe, precisamos ter uma forma de sincronização e travamento dupla-verificação.

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

O código acima é o código mais eficiente para sistema de travamento dupla-verificação e o código é de alguma forma similar à função lazy() no Kotlin e é por isso que é chamado de inicialização preguiçosa. Assim, sempre que você quiser uma classe singleton com argumentos então você pode usar a classe SingletonHolder.

Aqui, no código acima, no lugar da função criadora que é passada como argumento para o SingletonHolder, uma lambda personalizada também pode ser declarada inline ou podemos passar uma referência para o construtor privado da classe singleton. Então, o código será:

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

Agora, o singleton pode ser facilmente invocado e inicializado escrevendo o código abaixo e isso é preguiçoso assim como seguro para threads 🙂

YourManager.getInstance(context).doSomething()

É isso para o blog do Singleton. Espero que você goste deste blog. Você também pode consultar o site do Kotlin. Para saber mais sobre alguns dos tópicos legais do Android, você pode visitar o nosso site de blogs e pode se juntar à nossa jornada de aprendizagem.

Keep Learning 🙂

Team MindOrks!

Deixe um comentário