Cinco Padrões de Projeto Fundamentais em Python

Fundamentos de Padrões de Projeto

Os padrões de projeto representam um conjunto de melhores práticas e soluções consolidadas para problemas recorrentes na engenharia de software. Eles abordam desafios como reutilização de código, escalabilidade de sistemas e manutenção da legibilidade. Em Python, esses padrões são categorizados em criaiconais, estruturais e comportamentais, aproveitando as características dinâmicas e orientadas a objetos da linguagem.

1. Padrão de Fábrica (Factory)

O Padrão de Fábrica é um padrão criacional que centraliza a lógica de instanciação de objetos. Ele desacopla a criação de objetos do seu uso, permitindo que o sistema seja estendido com novas implementações sem alterar o código cliente.

class EmailNotification:
    def send(self, message: str) -> None:
        print(f"Enviando e-mail: {message}")

class SmsNotification:
    def send(self, message: str) -> None:
        print(f"Enviando SMS: {message}")

class NotificationFactory:
    @staticmethod
    def get_notifier(channel: str):
        if channel == "email":
            return EmailNotification()
        elif channel == "sms":
            return SmsNotification()
        raise ValueError("Canal de notificação desconhecido")

notifier = NotificationFactory.get_notifier("email")
notifier.send("Bem-vindo ao sistema!")

2. Padrão Singleton

O Padrão Singleton garante que uma classe possua apenas uma instância durante o ciclo de vida da aplicação, fornecendo um ponto de acesso global. Em Python, uma abordagem robusta e pythonica para implementar este padrão é através do uso de metaclasses.

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class DatabaseConnection(metaclass=SingletonMeta):
    def __init__(self):
        self.connection = "Conexão ativa"

conn1 = DatabaseConnection()
conn2 = DatabaseConnection()

print(conn1 is conn2)  # Saída: True

3. Padrão Adaptador (Adapter)

O Padrão Adaptador atua como uma ponte entre duas interfaces incompatíveis. Ele é classificado como um padrão estrutural e é frequentemente utilizado para integrar componentes legados ou bibliotecas de terceiros que não possuem a assinatura de método esperada pelo sistema atual.

class ModernPaymentProcessor:
    def process_payment(self, amount: float) -> None:
        print(f"Processando pagamento moderno de ${amount}")

class LegacyPaymentGateway:
    def execute_card_transaction(self, value: float) -> None:
        print(f"Executando transação legada de ${value}")

class PaymentAdapter(ModernPaymentProcessor):
    def __init__(self, legacy_gateway: LegacyPaymentGateway):
        self._legacy_gateway = legacy_gateway

    def process_payment(self, amount: float) -> None:
        self._legacy_gateway.execute_card_transaction(amount)

legacy_system = LegacyPaymentGateway()
adapter = PaymentAdapter(legacy_system)
adapter.process_payment(150.00)

4. Padrão Decorador (Decorator)

O Padrão Decorador permite a adição de novas funcionalidades a um objeto de forma dinâmica e transparente. Python possui suporte nativo a decoradores através da sintaxe com o símbolo @, o que facilita a modificação do comportamento de funções e métodos sem alterar sua estrutura original.

import time
from functools import wraps

def measure_execution_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        print(f"Execução de '{func.__name__}' levou {end_time - start_time:.4f} segundos")
        return result
    return wrapper

@measure_execution_time
def heavy_computation():
    time.sleep(1)
    return "Cálculo concluído"

heavy_computation()

5. Padrão Observador (Observer)

O Padrão Obesrvador estabelece uma relação de dependência um-para-muitos entre objetos. Quando o estado do objeto principle (sujeito) é alterado, todos os seus dependentes (observadores) são notificados automaticamente. Este padrão é a base para arquiteturas orientadas a eventos e sistemas de publicação/assinatura.

class NewsAgency:
    def __init__(self):
        self._subscribers = []
        self._latest_news = ""

    def subscribe(self, subscriber):
        self._subscribers.append(subscriber)

    def unsubscribe(self, subscriber):
        self._subscribers.remove(subscriber)

    def publish_news(self, news: str):
        self._latest_news = news
        self._notify_subscribers()

    def _notify_subscribers(self):
        for subscriber in self._subscribers:
            subscriber.receive_update(self._latest_news)

class NewsSubscriber:
    def receive_update(self, news: str):
        pass

class MobileUser(NewsSubscriber):
    def receive_update(self, news: str):
        print(f"Notificação no celular: {news}")

agency = NewsAgency()
mobile_client = MobileUser()

agency.subscribe(mobile_client)
agency.publish_news("Python 3.12 lançado!")

Tags: Python design-patterns factory-pattern singleton-pattern adapter-pattern

Publicado em 7-5 21:06