Implementações Variadas do Padrão Singleton

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

Tags: singleton design patterns Python classmethod decorator

Publicado em 6-8 02:30 por Thomas