Introdução
Singleton é um padrão muito utilizado e muito útil dependendo do que se deseja fazer. Ele permite que exista somente uma instancia de uma determinada classe, como uma classe que gerencia a entrada do usuário.
Você poderia também criar uma classe utilizando somente membros estáticos para esse mesmo efeito, mas não seria mais eficiente do que o singleton.
Esse padrão permite alocar e desalocar da memória a instancia, economizando memória se isso for realmente um problema.
Apresentarei aqui a criação de uma classe singleton, que deverá servir de base para as classes que devem permitir somente uma instancia. Para utiliza-la, simplesmente crie uma classe derivada, implemente as funções herdadas (override) e pronto.
A classe singleton
Primeiramente, crie um arquivo chamado Singleton.h ou qualquer outro nome que ache apropriado e copie o codigo abaixo.
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
template <typename T> class Singleton
{
protected:
static T* mInstance;
public:
Singleton( void )
{
mInstance = static_cast< T* >( this );
}
~Singleton( void )
{
mInstance = 0;
}
static T& getSingleton( void )
{
return ( mInstance );
}
static T* getSingletonPtr( void )
{
return mInstance;
}
};
#endif
Implementando um classe derivada
Aqui apresento um exemplo de como criar sua classe derivada do Singleton. Note que esse é o mínimo requisito para se começar a utilizar a classe.
Você também poderia optar por implementar somente obter a instancia por referencia ou por ponteiro. Mas por flexibilidade, implemente os dois.
// MyClass.h
#include "Singleton.h"
class MyClass : public Singleton<MyClass>
{
public:
static MyClass& getInstance( void );
static MyClass* getInstancePointer( void );
};
Agora vamos ver o que deve ser colocado no arquivo cpp. Note que o corpo das funções poderia ser colocado na própria declaração da classe, ao invés de se separar, como é o caso desse exemplo.
// arquivo de implementação
// MyClass.cpp
template<> MyClass* Singleton<MyClass>::mInstance = NULL;
static MyClass& MyClass::getInstance( void )
{
return ( mInstance );
}
static MyClass* MyClass::getInstancePointer( void )
{
return mInstance;
}
Utilizando a classe derivada
Seu uso é simples e prático, veja um exemplo:
// Exemplo 1
void main()
{
MyClass *ptr = new MyClass;
ptr->metodo_qualquer();
delete ptr;
}
Agora um outro exemplo de como se utilizar dos métodos estáticos fornecidos pela classe.
// Exemplo 2
void main()
{
new MyClass;
MyClass::getInstance().metodo_qualquer();
delete MyClass::getInstancePointer();
}
Se desejar verificar se a instancia da classe foi criada, basta utilizar o método getInstancePointer(). Veja:
// Exemplo 2
void funcao_qualquer()
{
// verifica se MyClass foi criada
if ( MyClass::getInstancePointer() == NULL )
{
printf("MyClass não criado\n");
return;
}
MyClass::getInstance().metodo_qualquer();
}
Note também que não é necessário criar a instancia da classe através de alocação dinamica, também é possivel criar uma instancia normal, mas somente é aconselhável criar essa instancia sem alocação dinamica na função main.
|