2. Singleton
• Assegura que uma classe tenha apenas
uma instância e provê um ponto de
acesso global a ela
2 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
3. Motivação
• É importante a algumas classes ter
exatamente uma instância
– Ex.: várias impressoras, mas apenas um
spool de impressão. Um único sistema de
arquivos, um único gerenciador de janelas etc
– Como garantir a única instância e o acesso
fácil a ela?
• Variável global? é possível instanciar múltiplos
objetos...
3 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
4. Motivação
• A melhor solução é fazer a própria classe
responsável por manter “rastreável” sua
única instância.
– Assegurar que nenhuma outra instância seja
criada (interceptando requisições de criação
de novos objetos)
– Prover uma forma de acesso a esta instância
• Esta solução é o padrão Singleton
4 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
5. Aplicação
• Use Singleton quando:
– Deve haver exatamente uma instância de
uma classe e ela deve ser acessível a
clientes a partir de um ponto de acesso bem
conhecido
– A instância única deve ser extensível via
especialização e os clientes devem ser aptos
a usar uma instância estendida sem modificar
seu código
5 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
6. Estrutura
6 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
7. Participante
• Singleton
– Define uma operação Instance que permite
aos clientes acessarem sua instância única.
Instance é uma operação da classe (isto é,
uma função membro estática em C++)
– Pode ser responsável por criar sua própria
instância única
7 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
8. Colaborações
• Clientes acessam a instância de um
Singleton apenas através da operação
Instance do Singleton
8 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
9. Conseqüências
1. Acesso controlado à instância única
2. Espaço de nomes reduzido
3. Permite um número variável de
instâncias
4. Mais flexível que operações de classe
9 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
10. Implementação
• Assegurar uma instância única: esconder
a operação que cria a instância atrás de
uma operação de classe que garanta que
somente uma instância seja criada
10 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
11. Implementação
• Note que o construtor é protegido. Um cliente que tente
inicializar Singleton diretamente receberá um erro em
tempo de compilação
• Note também que Instance usa lazy initialization
11 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
12. Implementação
• Veja que não basta apenas definir o singleton como uma
variável global ou objeto estático, porque:
– Não é possível garantir que somente uma instância de um
objeto estático seja declarada
– Pode-se não ter toda a informação necessária para a
instanciação de todo singleton no instante da inicialização
estática
– C++ não define a ordem na qual os construtores para objetos
globais são chamados, isto significa que não pode haver
nenhuma dependência entre singletons, caso contrário, erros
serão inevitáveis.
– Além é claro, da desvantagem de objetos globais/estáticos
(todos os singletons são criados, independente deles serem
usados ou não)
12 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
13. Implementação
• Especializando classes Singleton
– A técnica mais simples é determinar qual singleton se
quer usar de dentro da operação Instance (p.ex., via
variável de ambiente)
– Outra forma de se escolher a subclasse de Singleton
é colocar Instance dentro das subclasses (liga-se um
objeto que contém uma implementação diferente –
portanto, escondendo-se isto da implementação do
cliente)
– Uma terceira forma é usar um registro de
singletons
13 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
14. Implementação - Registro
• Ao invés de Instance definir um conjunto de
possíveis classes Singleton, as classes
Singleton registram suas instâncias pelo nome
em um registro bem conhecido
• O registro mapeia entre nomes e singletons
• Quando Instance precisa de um singleton, ele
consulta o registro pelo nome
• O registro procura pelo singleton
correspondente (se existe) e o retorna
• Esta técnica libera Instance de ter que conhecer
todas as possíveis classes de Singleton
14 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
15. Implementação
15 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
16. Implementação
16 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
17. Implementação
• Onde as classes Singleton se registram?
• Em seu construtor?
• Problema: o construtor só é chamado se a
classe já tiver sido chamada...
17 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
18. Implementação
• Solução: definir uma instância estática
• Neste caso, a classe não é mais responsável
por criar o singleton, mas apenas torná-lo
acessível no sistema.
• A desvantagem é que as instâncias de todas as
possíveis subclasses Singleton devem ser
criadas ou não serão registradas
18 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
19. Exemplo
No exemplo da MazeFactory, precisa-se
apenas de uma única instância da fábrica
de labirinto.
Exemplo 1: considera-se que nunca haverá
subclasses de MazeFactory
Exemplo 2: há subclasses de MazeFactory
19 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
20. Exemplo 1
20 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
21. Exemplo 1
21 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
22. Exemplo 2
22 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
23. Exemplo 2
• Note que Instance deve ser modificada
sempre que se define uma nova
subclasse de MazeFactory
• Uma possível solução é o registro de
singletons
• Outra solução é fazer “linkagem”
dinâmica.
23 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma
24. Exemplo
• Para criar um labirinto que contenha
cômodos encantados, basta chamar
CreateMaze de um
EnchantedMazeGame:
EnchantedMazeGame game;
game.CreateMaze();
24 Livro Texto: Design Pattern - Elements Eduardo N. F. Zagari
of Reusable OO Software - Gamma