A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Aula 11 – Padrão Singleton

Apresentações semelhantes


Apresentação em tema: "Aula 11 – Padrão Singleton"— Transcrição da apresentação:

1 Aula 11 – Padrão Singleton
Padrões de Projeto Aula 11 – Padrão Singleton

2 Façade Definição: Quando usar? Tipo de padrão? Como? estrutural

3 Padrão Singleton coisa única When ONE is ENOUGH!

4 Definição O padrão Singleton garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela. Hoje começaremos pela definição.

5 When is one enough? Geralmente, quando um recurso global é compartilhado; Aplicações multi-threaded; Aplicações que acessam dados externos banco de dados; impressora; driver de dispositivo; Também é bastante utilizado para logging, caching, pools de threads, preferências e configurações de sistemas, etc. Banco de dados: geralmente é utilizada apenas um objeto para realizar a conexão com o banco, porque um objeto é suficiente, para a maioria das aplicações; Logging: apenas um OutputStream é necessário para “loggar” em um arquivo… Impressão: apenas um spooler de impressão é necessário, não importando a quantidade de clientes que o utilizem…

6 Como garantir uma única instância?
Como você criaria um único objeto? E se outro objeto quisesse criar um MyObject? Poderia chamar new em MyObject de novo? Então, se tivermos uma classe, sempre poderemos instanciá-la uma ou mais vezes? E se não for? new MyObject(); Sim, claro. Sim, mas só se for uma classe pública. Se não for pública, apenas as classes do mesmo pacote poderão instanciá-la mais de uma vez.

7 Como garantir uma única instância?
Vocês sabiam que isso é possível? O que isto significa? Então, quem poderia usar esse construtor? Por que não? Nunca havíamos pensado a respeito. Mas parece ser possível. Parece ser uma classe que não pode ser instanciada porque o construtor é private. Hmm... Qualquer código dentro de MyClass tem acesso e pode chamar esse construtor privado. Mas isso não faz muito sentido. Porque seria preciso ter uma instância da classe para chamá-lo. Mas como essa primeira instância é criada? public class MyClass{ private MyClass(){} }

8 Como garantir uma única instância?
E se MyClass tivesse um método static? Hmmmmmmmm... Assim nós conseguimos usar getInstance e usar o construtor privado para pegar o objeto. public class MyClass{ private MyClass(){} public static MyClass getInstance(){ return new MyClass(); } Mas como garantir que somente UMA única instância (singleton) de MyClass seja criada? Hands on!

9 Implementação clássica
Agora chamamos MyClass de Singleton Temos uma variável estática para conter nossa única instância da classe Singleton public class Singleton{ private static Singleton uniqueInstance; //other variables private Singleton(){} public static Singleton getInstance(){ if(uniqueInstance==null) uniqueInstance = new Singleton(); return uniqueInstance; } //other methods Nosso construtor é privado. Apenas Singleton tem acesso a ele. Singleton é uma classe normal, e por isso tem outras variáveis que não a que contém a instância de Singleton, bem como também contem outros métodos. Por ser estático, getInstance é a nossa única maneira de conseguirmos uma instância de Singleton. Nele colocamos um código que permite uma única instanciação da classe Singleton.

10 Implementação clássica
Note que essa é a lazyInitialization (instanciação preguiçosa). O objeto só é criado quando alguma classe chama getInstance. Mais adiante veremos outros tipos de inicialização. uniqueInstance contém nossa única instância; lembre-se é uma variável estática public class Singleton{ private static Singleton uniqueInstance; //other variables private Singleton(){} public static Singleton getInstance(){ if(uniqueInstance==null) uniqueInstance = new Singleton(); return uniqueInstance; } //other methods Se uniqueInstance é nulo então é porque ainda não criamos a instância E caso não exista, o instanciamos através de seu construtor privado Se uniqueInstance não for nula é porque já foi criada. Então, apenas retornamos uniqueInstance.

11

12 Quando ele fala solteiro, no livro em inglês ele diz single
Quando ele fala solteiro, no livro em inglês ele diz single. Traduziram errado. Solteiro, aí, quer dizer único. 

13 Exercício (10 min) Crie uma classe chamada GerenciadorDeTempo que tem como variável de instância um inteiro para representar o tempo. Crie getters e setters para tempo; No construtor, inicialize a variável tempo com o valor 1; Transforme a classe GerenciadorDeTempo em um Singleton; Verifique se você realizou um bom trabalho 

14 Terminologia e Estrutura
getInstance() é static, ou seja, podemos acessá-lo de qualquer outra classe uniqueInstance contém a única instância de Singleton Singleton deve ter um construtor private. Lembre-se disto. Uma classe que implementa o padrão Singleton é mais do que um Singleton; é uma classe de fins gerais com seu conjunto de dados e métodos

15 Exemplo com Thread Uma máquina multi-core, executanto o programa da Fábrica de chocolate com duas threads chamando getInstance()… Analise o valor de uniqueInstance ao longo do tempo. Thread 1 Thread 2 public static ChocolateBoiler getInstance(){ if(uniqueInstance==null) uniqueInstance = new ChocolateBoiler(); return uniqueInstance; } tempo

16 Problemas com Multithreading
Quando há multithreading o método getInstance() poderia ser chamado mais ou menos no mesmo instante, o que resultaria em mais de uma instância sendo criada; Possíveis soluções: Sincronizar o método getInstance() Utilizar a estratégia de eager initialization ao invés de lazy initialization Usar a trava duplamente verificada para reduzir o uso da sincronização em getInstance()

17 Sincronizando getInstance()
public static synchronized ChocolateBoiler getInstance(){ if(uniqueInstance==null) uniqueInstance = new ChocolateBoiler(); return uniqueInstance; } Desvantagem: pode diminuir o desempenho do programa por um fator de 100; Se o desempenho de getInstance não for crítico para o seu aplicativo, essa pode ser uma boa saída. Explicar o synchronized explicando que o lock é como se fosse uma chave, e a thread só poderá executar aquele trecho de código quando estiver em posse da chave.

18 ansioso, apressado Eager Initialization public class Singleton{ private static Singleton uniqueInstance = new Singleton(); //other variables private Singleton(){} public static Singleton getInstance(){ return uniqueInstance; } //other methods Útil se você sabe que seu programa sempre cria e usa uma instância Singleton. O construtor será chamado na primeira vez que a classe for carregada, ou seja, quando você tentar executar algum método (não necessariamente o getInstance) da classe em questão. Testar eager e lazy initialization para entender melhor as diferenças

19 Trava duplamente verificada
public class Singleton{ private volatile static Singleton uniqueInstance; //other variables private Singleton(){} public static Singleton getInstance(){ if(uniqueInstance==null){ synchronized(Singleton.class){ if(uniqueInstance==null) uniqueInstance = new Singleton(); } return uniqueInstance; //other methods Garante que várias threads lidem com a variável uniqueInstance corretamente Procure uma instância, e se não houver uma, insira um bloco sincronizado Observe que sincronizamos, apenas na primeira vez (criação). Uma vez no bloco, verifique de novo, e, se ainda for null, crie uma instância. Diminui o overhead imposto pela sincronização entre as threads (synchronized)

20 Resumo Permite que exista apenas UMA instância da “classe Singleton”;
Provê um ponto de acesso único e global; É implementado declarando o contrutor private e um método static combinado com uma variável static; É preciso tomar cuidado quando há mais de uma thread criando a instância Singleton. Há três formas de resolver esse problema, cada uma com sua peculiaridade (vantagens e desvantagens): Declarando getInstance() como synchronized; Eager initialization; Trava duplamente verificada.

21 Referências [1] Capítulo 5 do livro “Padrões de Projeto – Use a Cabeça!”


Carregar ppt "Aula 11 – Padrão Singleton"

Apresentações semelhantes


Anúncios Google