Monday, May 11, 2009Singleton em Java
Simples post para demonstrar o uso do Design Pattern Singleton em Java.
Assegura que uma determinada classe tenha apenas uma única instância, e apenas um meio de acesso a mesma.
Por exemplo em um sistema operacional é o uso de impressoras, temos vários clientes conectados a impressora, mas a mesma possui apenas um spool de documentos.
Segundo Gof temos o diagrama abaixo:
E como codificar isso? Imagine um cenário seguinte, precisamos desenvolver um chat entre múltiplos clientes,
onde todos podem se comunicar com todos, de que forma podemos implementar e assegurar que todos os usuários do nosso chat acessem exclusivamente a mesma instância da classe?
package br.com.ronaldorigoni.singleton;
/**
* Exemplo de Singleton - ChatRoom
* @author ronaldorigoni.com.br
*/
public class ChatRoom {
/**
* Única instancia da sala de bate papo, deve ser privada para
* não permitir acesso direto.
*/
private static ChatRoom instance = null;
/**
* Construtor privado para não permitir a
* criação de novas instancias da classe.
*/
private ChatRoom(){
// aqui codigo para a inicialização do chat.
// verifica configurações em banco ou outras
// operações.
}
/**
* Única forma de acesso para a instancia "instance" da classe
* @return - A única instância da sala de Chat
*/
public static ChatRoom getInstance(){
if(instance == null)
instance = new ChatRoom();
return instance;
}
}
Através do método getInstance(), qualquer cliente tem apenas uma forma de acesso e em uma única instancia da sala de Chat.
Agora criaremos um método writeMessage(String message):
/**
* Envia uma mensagem a todos os usuários
* @param message
*/
public void writeMessage(String message){
for(User user : userList){
user.sendMessage(message);
}
}
Mesmo o método sendo public, só conseguiremos acessar ele através de uma instancia da classe desta forma:
ChatRoom.getInstance().writeMessage("Mensagem de teste");
Mas cuidado, em um ambiente MultiThread não está seguro que existe apenas uma instancia da classe, se em um determinado momento duas threads acessarem o método getInstance() ao mesmo tempo será criada duas instancias.
Como bloquear isso? Adicionaremos um bloco s no método getInstance(), desta forma garantimos que toda Thread que entrar neste bloco irá bloquear o objeto instance para si mesmo, e só fará o desbloqueio quando o bloco de código terminar, assim uma vez desbloqueado estará disponível para uma nova thread utilizar.
public static ChatRoom getInstance() {
// garante que apenas uma thread por vez
// executará este bloco de código
synchronized (instance) {
if (instance == null)
instance = new ChatRoom();
}
return instance;
}
Para deixarmos nosso exemplo mais seguro, muitos desenvolvedores acham este método bizarro, mas eu o utilizei varias vezes, altere o método getInstance() para o modificador de acesso private, em seguida crie uma classe interna conforme abaixo, esta classe deve ser public static abstract, mas espere aí? Classe estatica é possível? Sim classe static é possível desde que a mesma seja aninhada ( classe interna).
private static ChatRoom getInstance() {
synchronized (instance) {
if (instance == null)
instance = new ChatRoom();
}
return instance;
}
E agora nossa classe interna aninhada:
public abstract static class ChatRoomHolder{
public static ChatRoom getInstance(){
return ChatRoom.getInstance();
}
}
Repare que a classe é abstrata, com isso fica impossível instanciá-la, mas por ela ser interna ela tem acesso aos métodos private de nossa ChatRoom, invoca o método getInstance() e retorna a instancia criada no construtor.
Desta forma estamos garantindo de duas maneiras que a classe ChatRoom tenha apenas uma única instancia:
- Com o uso de construtor privado e um bloco sincronizado no método getInstance().
- Com o uso de uma classe abstrata interna que não permite ser instanciada por ser abstrata.
Singleton pode ser aplicado em diversos casos, ( conexão a banco de dados, mecanismo de Log, Objetos de configuração, etc…).
Dúvidas, ronaldo@ronaldorigoni.com.br
Até um próximo post.
Português
Italiano
English
Friday, July 24, 2009 at 14:59
Everything dynamic and very positively!
Saturday, July 25, 2009 at 18:42
Tanks,
Regards Ronaldo