Singleton e Adapter Professor: Nazareno Andrade (baseado no material de Hyggo Almeida e Jacques Sauvé) O que vimos na última aula? Factory Method Abstract Factory Singleton 2 O que veremos hoje? Singleton (padrão de criaçã) Adapter (padrão estrutural) Singleton 3 Problema-exemplo 1 Representar a configuração do sistema ¤ Timeout para mensagens ¤ Diretório para arquivos temporários ¤ ... Queremos que só haja uma instância da configuração Queremos um ponto único de acesso a essa configuração Outro exemplo Considere a seguinte arquitetura de sistema ¤ Vários módulos do sistema utilizam o mesmo BD ¤ Você gerencia as operações sobre o BD ¤ A classe ConexãoBD dá acesso ao banco módulo2 módulo3 módulo1 módulo4 :ConexãoBD :ConexãoBD :ConexãoBD :ConexãoBD BD Singleton 5 E se você quiser garantir que haja apenas uma conexão para todos os módulos? ¤ Como garantir que haja apenas uma instância de ConexãoBD? módulo2 módulo3 módulo1 módulo4 :ConexãoBD BD Singleton ??? 6 Solução toda estática Simples não é??!! Cria-se uma classe estática ¤ Métodos estáticos para acesso ao banco ¤ Atributos estáticos com informações de conexão ¤ Algoritmos de conexão encapsulados em métodos estáticos... ¤ E por aí vai... E a Orientação a objetos??? Onde é que fica??? ¤ Mudou a forma de conectar ao banco... mudaram as informações de configuração... ¤ Onde está a herança?!? Pois é amigo... não tem!!! Singleton 7 Singleton Eis a solução... Padrão Singleton Intenção ¤ garantir que uma classe tenha somente uma instância, fornecendo um ponto global de acesso para a mesma Aplicabilidade ¤ ¤ Singleton deve haver apenas uma instância de uma classe e essa instância deve dar acesso aos clientes através de um ponto bem conhecido quando a única instância tiver de ser extensível através de subclasses, possibilitando aos clientes usarem uma instância estendida sem alterar o seu código 8 Singleton Como construir um Singleton??? Código Java (passo a passo) 1. Precisamos garantir que só haja uma instância, ou seja, temos que impedir que se faça new ConexaoBD(), mais de uma vez... Solução: protegemos o construtor! public class ConexaoBD{ /* Construtor da classe */ protected ConexaoBD(){ //código do construtor... } } Singleton 9 Singleton 2. Precisamos agora fornecer um método de acesso à instância única criada... este método deve ser estático... public class ConexaoBD{ private static ConexaoBD instanciaUnica = null; /* Construtor da classe */ protected ConexaoBD(){...} /* Retorna a instância única */ public synchronized static ConexaoBD getInstance(){ if (instanciaUnica == null){ instanciaUnica = new ConexaoBD(); } return instanciaUnica; } } Singleton 10 Singleton Conseqüências ¤ acesso controlado à instância única ¤ evita a “poluição” do código com inúmeras variáveis globais ¤ mais flexível do que métodos de classe ¤ possibilita a herança Singleton 11 Singleton Vamos implementar o padrão Singleton ¤ ¤ Criar uma classe cliente para acessar o Singleton Verificar se realmente apenas uma instância foi criada... ¤ Recuperar a instância ¤ Alterar um valor de atributo ¤ Recuperar novamente a instância ¤ Verificar se o valor foi alterado ¤ Tentar criar uma instância, em outra classe, utilizando o operador new ¤ E se o construtor fosse privado? Singleton 12 Implementação: ¤ Método getInstance() vs. inicialização estática ¤ Problemas semelhantes a variáveis globais ¤ Diferença de construtor privado vs. protected ¤ Opção: classe abstrata com getInstance() que escolhe subclasse a ser instanciada (ex: java.awt.Toolkit) Bom exemplo: java.lang.Runtime (tem addShutdownHook(), getNumberOfProcessors, ...) Fachadas geralmente são Singletons Singleton 13 Problema-exemplo 2: Temos uma classe que formata séries de números para mostrar na interface Queremos filtrar objetos de classes nossas e legadas/de terceiros Como adaptar classes que possuem implementação que queremos à interface que precisamos? Problema exemplo 3: Uma interface gráfica baseada em eventos espera ActionListeners. Não queremos que nossas classes da lógica implementem essa interface Adapter Conseqüências ¤ ¤ ¤ O cliente e a classe adaptada se mantêm independentes um do outro Você “limpa” classes que são de propósito geral (diminui o número de interfaces implementadas) Dificulta o entendimento (introduz um nível de indireção) Adapter e Façade 16 Adapter Aplicabilidade ¤ É necessário usar uma classe que invoca um método através de uma interface, mas você quer usá-lo com uma classe que não implementa tal interface ¤ ¤ Você não tem o código fonte da classe A classe é de propósito geral e você não quer fazê-la implementar a interface Adapter e Façade 17 O que vimos hoje? Singleton Adapter Singleton 18 Dúvidas? ? Singleton 19