Typleton é completamente auto-suficiente. Essa classe é autocontida e não precisa de nenhuma outra classe. Por outro lado, Templeton precisa de algumas classes de apoio.
Por causa disso, e para organizar o código e a proliferação de classes, eu criei um namespace chamado featherns que irá conter todas as classes apresentadas nesse tutorial, de todos os Design Patterns que eu lhes mostrar. Featherns é o nome do projeto que eu criei para hospedar o código deste tutorial. Trata-se de uma combinação das palavras Feather (pena) e Patterns, resultando em Featherns.
O nome significa que este projeto, como uma biblioteca, é leve como uma pena e lida com Design Patterns. Featherns será uma biblioteca composta somente por arquivos de cabeçalho, assim como algumas bibliotecas do Boost. E eu pretendo que ela seja completamente portátil, sem dependências externas. Essas dependências externas, por ironia, podem ser usada em Featherns através de Injeção de Dependência (como veremos mais tarde nesse mesmo post).
Acompanhando a classe parental de Templeton, cujo nome é SingletonController, precisamos definir uma exceção que será lançada se Templeton for instanciada mais de uma vez. Chamei essa classe de MultiSingletonException e ela é uma classe derivada da classe std::exception fornecida pela Biblioteca Padrão C++. Mas isso não é suficiente, precisamos vincular Templeton corretamente a SingletonController, e essa vinculação correta é através de herança privativa, não através da herança pública, que é muito mais comum. Vamos ao código fonte:
Figura 4
Como pode ser visto, depois de todas as explicações dadas acima, a codificação de Templeton é bastante simples. Templeton usa uma funcão de controle externa, chamada SingletonController::initialize, como pode ser visto na linha 30 da Figura 4; no lugar de uma função local, como ocorre em Typleton. Uma vez que SingletonController não é um template, ele não é instanciável para diversos tipos, e a sua função de controle é sempre a mesma em todo o programa, não importando que classe foi usada para instanciar Templeton.
Templeton é realmente um Singleton de verdade. E um daqueles bastante restritivos. Ele só pode ser instanciado uma única vez em todo o programa, incluindo as suas bibliotecas compartilhadas e em qualquer biblioteca de componentes que o programa utilize. É uma força, mas, também, uma fraqueza. Templeton é tão restritiva que nós precisaremos relaxá-lo um pouquinho para deixá-lo efetivamente útil para o uso em Inversão de Controle. Mas esse post é a respeito de Singletons, não de Inversões de Controle. Portanto deixaremos para resolver esse problema mais tarde, no momento adequado.
Agora que tempos uma codificação real de um Singleton, é chegado o momento de mostrar alguns exemplos. Mas não vou fazê-lo. Irei, de forma sádica, ainda mais fundo dentro de Typleton e de Templeton. Essas duas classes são contêineres de ponteiros. Isso é bom. Gerenciamento de ponteiros, em C++, nos dá completo poder sobre o polimorfismo existente nas funções virtuais.
Atribuição de ponteiros é completamente segura em multithreading porque esses comandos são traduzidos pelo C++ (e também pelo C) em instruções de processamento atômicas. Mas o uso de Templeton e de Typleton é seguro em multithreading apenas se as suas classes parâmetro também forem seguras. Isso significa que todo controle de acesso a threads precisa ser feito pelos usuários dessas classes.
Isso é ruim, mas em Featherns não poderia ser diferente. Controle de acesso a threads é código dependente de plataforma e Featherns tem como objetivo ser autocontida e independente de plataforma. Mas eu posso dar uma pequena ajuda, oferecendo na biblioteca classes que definam um padrão de implementação de segurança em multithreading nos Singletons. Featherns não oferecerá controle de acesso a threads, mas irá oferecer como e onde colocar o controle de acesso.
Agora chegamos em um ponto de inflexão. Explicar em mínimos detalhes como implementar segurança em multithreading em Typleton e Templeton seria cansativo, e não adicionaria nenhum valor informacional a esse tutorial. Então ofereço a vocês o link para a primeira versão liberada do arquivo de cabeçalho que contém Typleton e Templeton. Obtenha tal arquivo
neste link.
Dê uma parada para descansar. Leia o arquivo Singleton.h com cuidado. Agora é o momento de partirmos para as Injeções de Dependência.