O padrão Singleton é um padrão de design que assegura que uma classe possua somente uma instância e disponibiliza um ponto de acesso global a ela. Em outras palavras, múltiplas instancições devem retornar o mesmo objeto, diferentemente de classes comuns onde objetos distintos, mesmo com propriedades e métodos idênticos, ocupam locais diferentes na memória.
A seguir, são apresentadas algumas formas de implementar esse padrão em Python, com exemplos adaptados para ilustrar variações de estrutura e lógica.
Implementação Baseada em classmethod
class ConexaoBanco:
_instancia = None
def __init__(self, endereco, porta):
self.endereco = endereco
self.porta = porta
@classmethod
def obter_instancia(cls):
if cls._instancia is None:
cls._instancia = ConexaoBanco('localhost', 5432)
return cls._instancia
instancia1 = ConexaoBanco.obter_instancia()
instancia2 = ConexaoBanco.obter_instancia()
print(instancia1 is instancia2) # Saída: True
Implementação Baseada em Decorator
def singleton_decorator(cls):
_instancia = cls('localhost', 5432)
def envolvedor(*args, **kwargs):
if args or kwargs:
return cls(*args, **kwargs)
return _instancia
return envolvedor
@singleton_decorator
class ServicoCache:
def __init__(self, host, port):
self.host = host
self.port = port
obj_a = ServicoCache()
obj_b = ServicoCache('outrohost', 8080)
obj_c = ServicoCache()
print(obj_a is obj_c) # Saída: True
print(obj_a is obj_b) # Saída: False
Implementação Baseada em Metaclass
class MetaSingleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instancia'):
cls._instancia = super().__call__(*args, **kwargs)
return cls._instancia
class GerenciadorRecursos(metaclass=MetaSingleton):
def __init__(self, config, max_conexoes):
self.config = config
self.max_conexoes = max_conexoes
rec1 = GerenciadorRecursos('config1', 10)
rec2 = GerenciadorRecursos('config2', 20)
print(rec1 is rec2) # Saída: True
Implementação Baseada em __new__
class SingletonBase:
_instancia = None
def __new__(cls, *args, **kwargs):
if cls._instancia is None:
cls._instancia = super().__new__(cls)
return cls._instancia
class Logger(SingletonBase):
def __init__(self, nivel):
self.nivel = nivel
logger1 = Logger('DEBUG')
logger2 = Logger('INFO')
print(logger1.nivel) # Saída: DEBUG (mantém a primeira instância)
Implementação Baseada em Módulo
Em Python, módulos são singleton por natureza. Uma abordagem comum é criar uma instância única em um módulo separado e importá-la confrome necessário.
# Arquivo: configuracao.py
class Configuracao:
def __init__(self, ambiente):
self.ambiente = ambiente
instancia_global = Configuracao('produção')
# Em outro arquivo:
from configuracao import instancia_global as config
print(config.ambiente) # Saída: produção