Como criar um singleton em C++

Como Criar Um Singleton Em C



Em C++, um singleton é um princípio de design que garante a presença de uma instância solitária da classe em todo o programa e fornece um ponto de acesso global para essa instância específica.

O padrão singleton é comumente usado quando você precisa ter um recurso único e compartilhado que deve ser acessado globalmente, como uma conexão de banco de dados, um criador de logs ou um gerenciador de configuração. Ao impor uma única instância, permite que múltiplas partes do programa acessem e modifiquem o mesmo objeto, promovendo a consistência dos dados e reduzindo a necessidade de variáveis ​​globais. Singleton pode ser empregado como um cache de objetos onde os objetos usados ​​com frequência ou de criação cara são armazenados e reutilizados em todo o aplicativo. Essa abordagem ajuda a melhorar o desempenho, evitando a criação e inicialização redundantes de objetos.

Neste artigo, explicaremos a criação de um singleton e demonstraremos um exemplo de estilização de um singleton em um programa C++.







Exemplo 1: Criando um Singleton Simples com Inicialização Eager

Um singleton simples com inicialização antecipada é um padrão de design que garante que apenas uma instância de uma classe seja criada e seja criada avidamente durante a inicialização estática.



Demonstraremos o trecho de código básico para a criação de um singleton simples com inicialização rápida. Vamos começar com o programa:



#include

classe Singleton {
privado :
estático Solteiro * instância ;
Solteiro ( ) { }
público :
estático Solteiro * getInstance ( ) {
retornar instância ;
}
} ;


Solteiro * Solteiro :: instância = novo singleton ( ) ;

interno principal ( ) {

Solteiro * singletonInstance1 = Solteiro :: getInstance ( ) ;

Solteiro * singletonInstance2 = Solteiro :: getInstance ( ) ;

padrão :: corte << 'singletonletonInstance1:' << singletonInstance1 << padrão :: fim ;

padrão :: corte << 'singletonletonInstance2:' << singletonInstance2 << padrão :: fim ;

retornar 0 ;

}

O código inclui o cabeçalho que fornece a funcionalidade para trabalhar com fluxos de entrada e saída como “std::cout”.





Após incluir o arquivo de cabeçalho, definimos a classe “Singleton” que representa a implementação do padrão singleton. Possui um construtor privado e uma variável de membro estático privada chamada “instância”.

Em seguida, a função getInstance() é implementada como uma função de membro público estático da classe “Singleton”. Ele retorna a instância do singleton que está armazenada na instância da variável de membro estático. A instância da variável de membro estático é definida e inicializada fora da classe com “Singleton* Singleton::instance = new Singleton();”. Esta linha inicializa a instância da classe “Singleton” avidamente durante a inicialização estática.



Na função main(), declaramos dois ponteiros, “singletonInstance1” e “singletonInstance2”, e atribuímos o valor que é retornado chamando Singleton::getInstance(). Como a instância é inicializada antecipadamente, ambos os ponteiros apontam para a mesma instância. As instruções “std::cout” imprimem os endereços de memória de “singletonInstance1” e “singletonInstance2” no console usando o operador “<<” e “std::endl”.

O código termina com um “retorno 0” que indica uma execução bem-sucedida do programa.

Quando você executa este código, a saída é mais ou menos assim:

A saída exibe os endereços de memória de “singletonInstance1” e “singletonInstance2”. Como ambos os ponteiros são atribuídos à mesma instância obtida de Singleton::getInstance(), eles têm o mesmo endereço de memória. Isso demonstra como o padrão singleton garante que haja uma única instância da classe e que as chamadas futuras para getInstance() sempre resultem na mesma instância.

Exemplo 2: Implementação de padrão Singleton com inicialização lenta

Esta demonstração explica a implementação do padrão singleton com inicialização lenta e mostra seu uso na função main(). A explicação passo a passo do trecho de código é fornecida após este programa:

#include

classe Singleton {

privado :

estático Solteiro * instância ;

Solteiro ( ) {

padrão :: corte << 'Instância Singleton criada.' << padrão :: fim ;

}

público :

estático Solteiro * getInstance ( ) {

se ( instância == nullptr ) {

instância = novo singleton ( ) ;

}

retornar instância ;

}

vazio Mostrar mensagem ( ) {

padrão :: corte << 'Olá de Singleton!' << padrão :: fim ;

}

~Singleton ( ) {

padrão :: corte << 'Instância Singleton destruída.' << padrão :: fim ;

}

} ;

Solteiro * Solteiro :: instância = nullptr ;

interno principal ( ) {

Solteiro * singletonInstance1 = Solteiro :: getInstance ( ) ;

singletonInstance1 -> Mostrar mensagem ( ) ;

Solteiro * singletonInstance2 = Solteiro :: getInstance ( ) ;

singletonInstance2 -> Mostrar mensagem ( ) ;

retornar 0 ;

}

O programa começa adicionando o arquivo de cabeçalho para realizar as tarefas de entrada/saída. Em seguida, declaramos e definimos uma classe “Singleton”. A única instância da classe é mantida dentro da variável de membro estático privado chamada “instância”.

Sempre que o construtor da classe “Singleton” é chamado, ele gera uma instância da classe “Singleton”. Ele envia a mensagem “Instância Singleton criada” para o console usando “std::cout <<… << std::endl;”. O construtor não possui parâmetros, pois é um construtor padrão. É definido como Singleton() sem quaisquer argumentos. Nós o declaramos como privado, o que significa que só pode ser invocado de dentro da classe. Isso evita uma instanciação direta da classe “Singleton” e garante que a única maneira de obter uma instância é através da função getInstance().

O método getInstance() da classe “Singleton” é declarado como uma função de membro estático público. Tem a função de estabelecer e conceder acessibilidade à instância singleton. Dentro do getInstance(), ele verifica se a instância é “nullptr”. Se estiver, significando que a instância ainda não está presente, ele usa o construtor privado para instanciar um novo objeto da classe “Singleton”.

A função showMessage() é uma função de membro simples que exibe a mensagem “Hello from Singleton!” mensagem. O destruidor do singleton está definido. É chamado implicitamente quando o programa termina e imprime a “instância Singleton destruída”. mensagem que indica que a instância singleton foi destruída. A instância da variável de membro estático é inicialmente definida como “nullptr”.

O int main() inicia a definição da função main(). Então, o “Singleton* singletonInstance1 = Singleton::getInstance();” chama a função getInstance() da classe “Singleton” para obter um ponteiro para a instância singleton. Ele atribui este ponteiro à variável “singletonInstance1”.

Depois disso, o “singletonInstance1->showMessage();” usa o operador de seta (->) para chamar a função showMessage() no ponteiro “singletonInstance1”. Esta função exibe a mensagem especificada nela para o console. Depois, o “Singleton* singletonInstance2 = Singleton::getInstance();” chama a função getInstance() novamente, obtendo outro ponteiro para a instância singleton. Desta vez, ele atribui o ponteiro à variável “singletonInstance2”. O “singletonInstance2->showMessage();” chama a função showMessage() no ponteiro “singletonInstance2”. Esta função exibe a mensagem “Hello from Singleton!” mensagem novamente para o console.

Por último, “retorne 0;” significa o fim da função main() e o programa retorna o valor 0, o que significa uma execução bem-sucedida do programa.

Aqui está a saída do trecho de código explicado anteriormente:

Este resultado confirma que a classe “Singleton” garante a criação de apenas uma instância e que chamadas adicionais para a função getInstance() geram a mesma instância de forma confiável.

Conclusão

Criar um singleton em C++ é um conceito muito útil. Nesta postagem, cobrimos inicialmente a seção de introdução do singleton. Além disso, dois exemplos são produzidos para implementar o singleton em C++. A primeira ilustração mostra a implementação da inicialização singleton ansiosa. Considerando que a implementação de inicialização lenta do padrão singleton é fornecida no segundo exemplo deste artigo. Além disso, os instantâneos da saída produzida também são exibidos para os programas correspondentes.