Padrão Criacional: Singleton

Dec 04 2022
Este artigo discute como o padrão Singleton obriga apenas uma única instância de uma classe a ser produzida e existir durante o tempo de vida de um aplicativo. O que é isso? Um singleton é um padrão de design usado para criar a única instância de classe.

Este artigo discute como o padrão Singleton obriga apenas uma única instância de uma classe a ser produzida e existir durante o tempo de vida de um aplicativo.

O que é isso?

Um singleton é um padrão de design usado para criar a única instância de classe. O padrão Singleton é normalmente usado quando há vários exemplos em que apenas uma única instância de uma classe deve existir e a restrição deve ser aplicada. Por exemplo, caches, pools de encadeamentos e registros devem ter apenas uma instância.

Torne o construtor privado para garantir que apenas um objeto de classe seja criado. Dessa forma, apenas os membros da classe podem acessar o construtor privado e mais ninguém.

No mundo real, o padrão Singleton garante que exista apenas uma única instância de classe e oferece um ponto global de acesso a ela.

Diagrama de classe

O diagrama de classes contém apenas uma entidade.

solteiro

Exemplo

Digamos que queremos modelar a aeronave oficial do presidente americano chamada Airforce One em nosso software. A classe Singleton é a representação mais adequada para uma entidade com apenas uma instância.

Aqui está o código para nossa classe singleton:

Multithreading e Singleton

Esse código funciona desde que o aplicativo seja de thread único. No entanto, se vários threads acessarem essa classe, existe a possibilidade de vários objetos serem criados.

Por exemplo:

  • A thread A chama o método getInstancee descobre que o onlyInstanceé nulo; no entanto, antes que ele possa criar uma instância, ele é trocado de contexto.
  • Agora o thread B vem e chama getInstance, que retorna o AirforceOneobjeto.
  • Se o thread A for agendado novamente, o dano começa. O thread já passou pela verificação de condição if-null e continuará criando um novo AirforceOneobjeto e atribuindo-o a onlyInstance. Agora existem dois AirforceOneobjetos diferentes na natureza, um com thread A e outro com thread B.
  • Ao adicionar synchronizedao getInstance()método, você pode obter a segurança do encadeamento.
  • Outra opção é inicializar a instância estaticamente, garantindo que ela seja thread-safe.

Bloqueio duplamente verificado

Existem dois problemas significativos com as abordagens descritas acima: a sincronização é cara e a inicialização estática cria o objeto mesmo que ele não seja usado em uma determinada execução de aplicativo. Se a criação do objeto for cara, a inicialização estática pode nos custar desempenho.

A solução acima marca a instância singleton volátil. No entanto, essa implementação da volatilemetodologia da JVM não funcionará corretamente para o bloqueio verificado duas vezes e você precisará de outra abordagem para criar seus singletons.

O idioma de bloqueio verificado duas vezes agora é considerado um antipadrão, e seu utilitário acabou principalmente porque os tempos de inicialização da JVM aceleraram.

Outros exemplos

A API Java nos fornece os seguintes singletons:

java.lang.Runtime

java.awt.Desktop

Ressalvas

Você pode criar uma subclasse de uma classe singleton protegendo o construtor em vez de private. No entanto, existem escolhas melhores do que isso em todas as circunstâncias. Nessas situações, os desenvolvedores podem criar um registro de singletons para todas as subclasses. O método getInstance pode receber um parâmetro ou usar uma variável de ambiente para retornar o objeto singleton desejado. O registro mantém um mapeamento de nomes de string para objetos singleton.

Outros artigos da série Creational Pattern