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