Eu li que é possível implementar Singleton
em Java usando um Enum
como:
public enum MySingleton {
INSTANCE;
}
Mas, como isso funciona? Especificamente, um Object
deve ser instanciado. Aqui, como está MySingleton
sendo instanciado? Quem está fazendo new MySingleton()
?
java
design-patterns
enums
singleton
Anand
fonte
fonte
INSTANCE
é igualpublic static final MySingleton INSTANCE = new MySingleton();
.Respostas:
Este,
tem um construtor vazio implícito. Torne explícito,
Se você adicionou outra classe com um
main()
método comoVocê veria
enum
Os campos são constantes de tempo de compilação, mas são instâncias de seuenum
tipo. E eles são construídos quando o tipo de enum é referenciado pela primeira vez .fonte
private
modificador não tem significado para umenum
construtor e é totalmente redundante.Um
enum
tipo é um tipo especial declass
.Seu
enum
será realmente compilado para algo comoQuando seu código for acessado pela primeira vez
INSTANCE
, a classeMySingleton
será carregada e inicializada pela JVM. Esse processo inicializa ostatic
campo acima uma vez (preguiçosamente).fonte
public enum MySingleton { INSTANCE,INSTANCE1; }
e depoisSystem.out.println(MySingleton.INSTANCE.hashCode()); System.out.println(MySingleton.INSTANCE1.hashCode());
imprime códigos de hash diferentes. Isso significa que dois objetos do MySingleton são criados?enum
constantes de diferença .Neste livro de práticas recomendadas de Java de Joshua Bloch, é possível explicar por que você deve aplicar a propriedade Singleton a um construtor particular ou a um tipo Enum. O capítulo é bastante longo, portanto, mantendo-o resumido:
Tornar uma classe um Singleton pode dificultar o teste de seus clientes, pois é impossível substituir uma implementação simulada por um singleton, a menos que implemente uma interface que sirva como seu tipo. A abordagem recomendada é implementar Singletons simplesmente criando um tipo de enumeração com um elemento:
Essa abordagem é funcionalmente equivalente à abordagem de campo público, exceto que é mais concisa, fornece o mecanismo de serialização gratuitamente e oferece uma garantia rígida contra instanciações múltiplas, mesmo em face de sofisticados ataques de serialização ou reflexão.
fonte
Como todas as instâncias enum, o Java instancia cada objeto quando a classe é carregada, com alguma garantia de que é instanciada exatamente uma vez por JVM . Pense no
INSTANCE
declaração como um campo final estático público: Java instancia o objeto na primeira vez em que a classe é referida.As instâncias são criadas durante a inicialização estática, definida na Especificação de Linguagem Java, seção 12.4 .
Pelo que vale, Joshua Bloch descreve esse padrão em detalhes como o item 3 do Effective Java Second Edition .
fonte
Como o padrão Singleton é sobre ter um construtor privado e chamar algum método para controlar as instanciações (como alguns
getInstance
), no Enums, já temos um construtor privado implícito.Não sei exatamente como a JVM ou algum contêiner controla as instâncias da nossa
Enums
, mas parece que ela já usa um implícitoSingleton Pattern
, a diferença é que não chamamos de agetInstance
, apenas chamamos de Enum.fonte
Como já foi mencionado, até certo ponto, uma enum é uma classe java com a condição especial de que sua definição deve começar com pelo menos uma "constante enum".
Além disso, e que enum não podem ser estendidos ou usados para estender outras classes, um enum é uma classe como qualquer classe e você a utiliza adicionando métodos abaixo das definições constantes:
Você acessa os métodos do singleton ao longo destas linhas:
O uso de um enum, em vez de uma classe, é, como foi mencionado em outras respostas, principalmente sobre uma instanciação segura do thread do singleton e uma garantia de que sempre será apenas uma cópia.
E, talvez, o mais importante, que esse comportamento seja garantido pela própria JVM e pela especificação Java.
Aqui está uma seção da especificação Java sobre como várias instâncias de uma instância enum são impedidas:
É importante notar que, após a instanciação, qualquer preocupação com a segurança do encadeamento deve ser tratada como em qualquer outra classe com a palavra-chave sincronizada etc.
fonte