Qual é o padrão de design Singleton?
O padrão singleton tem alguns casos de uso sólidos, portanto, saiba como usá-lo.
O padrão singleton é um dos padrões de design mais simples. Uma classe que usa o padrão de design singleton possui uma única instância que ela gerencia por conta própria. Esta classe impede que qualquer outra classe crie uma instância dela.
Uma classe singleton também fornece um único ponto de acesso global para a instância que ela cria. Portanto, qualquer classe que queira uma instância de uma classe singleton precisa acessá-la através de seu único ponto de acesso.
O excelente suporte do Java para programação orientada a objetos facilita o uso do padrão de design singleton.
Implementando o padrão Singleton usando Java
Existem muitas maneiras de implementar o padrão singleton em Java; as abordagens ansiosas e preguiçosas são variações comuns. Cada uma dessas abordagens tem seus próprios méritos e desvantagens. Portanto, o método que você escolher empregar deve depender de como seu aplicativo irá operar.
A abordagem ansiosa
Implementar o padrão singleton com a abordagem ansiosa significa que a classe cria uma nova instância de si mesma quando é carregada.
public class EagerSingleton {
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return instance;
}
}
A classe Java EagerSingleton cria uma nova instância de si mesma à medida que é carregada. Ele atribui esta instância à variável de instância estática privada, que só é acessível dentro da classe singleton. O único ponto de acesso externo à variável de instância é através do método getInstance(). Esse método retorna a instância da classe criada anteriormente.
Essa abordagem é ótima porque evita o problema de multithreading, que é um dos maiores desafios do padrão singleton. Ele resolve o problema de multithreading criando uma nova instância de si mesmo antes que qualquer novo thread possa acessar sua variável de instância. Isso garante que cada thread terá acesso apenas à mesma instância.
No entanto, a abordagem antecipada só será prática se seu aplicativo usar uma instância da classe singleton quando começar a ser executado. Caso contrário, você criará um objeto antes que seu aplicativo precise dele, usando recursos desnecessariamente.
A abordagem preguiçosa
A abordagem preguiçosa é a solução para o problema da abordagem ansiosa. Ele permite que você crie uma nova instância de uma classe singleton somente quando seu programa precisar dela.
public class LazySingleton {
private volatile static LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
A abordagem lenta resolve o problema de multithreading usando a palavra-chave synchronized. Isso evita que dois threads obtenham acesso à variável de instância ao mesmo tempo. Porém, sincronizar é caro, então o aplicativo só o usa uma vez, quando chama getInstance() pela primeira vez.
Quando usar o padrão Singleton
O padrão Singleton é útil em muitos cenários, para criar caixas de diálogo, manipular configurações de registro ou gerenciar pools de threads.
Outro uso comum para o padrão singleton é criar uma classe central que gerencia conexões de banco de dados.