Desenvolvimento Web

Design Patterns na Pratica: Os 10 Padroes Que Todo Desenvolvedor Precisa Conhecer

Design Patterns na Pratica: Os 10 Padroes Que Todo Desenvolvedor Precisa Conhecer

Design Patterns sao solucoes reutilizaveis para problemas comuns em design de software. Catalogados originalmente pelo Gang of Four (GoF) em 1994, continuam extremamente relevantes em 2026. Este guia cobre os 10 padroes mais importantes na pratica, com exemplos em codigo moderno.

O que sao Design Patterns e por que usar

Patterns nao sao codigo pronto para copiar — sao templates de solucao para problemas recorrentes. Usar patterns: cria vocabulario comum na equipe (todo dev sabe o que e um Observer ou Strategy), evita reinventar a roda para problemas ja resolvidos, produz codigo mais manutenivel e extensivel, facilita decisoes de design.

Mas cuidado: usar patterns desnecessariamente (over-engineering) e tao ruim quanto nao usar. Aplique quando o problema pede, nao forcadamente.

Padroes Criacionais

1. Singleton

Garante que uma classe tenha apenas uma instancia em toda a aplicacao. Uso: conexao de banco de dados, logger, configuracao global.

class DatabaseConnection:
_instance = None

@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
cls._instance._connect()
return cls._instance

def _connect(self):
self.connection = create_connection(“postgresql://…”)

Em frameworks modernos, Singleton e frequentemente substituido por injecao de dependencia com escopo singleton (Spring, NestJS).

2. Factory Method

Cria objetos sem especificar a classe exata. Delega a criacao para subclasses ou funcoes:

class NotificationFactory:
@staticmethod
def create(tipo, mensagem, destinatario):
if tipo == “email”:
return EmailNotification(mensagem, destinatario)
elif tipo == “sms”:
return SMSNotification(mensagem, destinatario)
elif tipo == “push”:
return PushNotification(mensagem, destinatario)
raise ValueError(f”Tipo desconhecido: {tipo}”)

# Uso
notificacao = NotificationFactory.create(“email”, “Bem-vindo!”, “user@email.com”)
notificacao.enviar()

3. Builder

Constroi objetos complexos passo a passo. Util quando um construtor teria dezenas de parametros:

class QueryBuilder:
def __init__(self):
self._select = “*”
self._from = “”
self._where = []
self._order_by = “”
self._limit = None

def select(self, campos):
self._select = campos
return self

def from_table(self, tabela):
self._from = tabela
return self

def where(self, condicao):
self._where.append(condicao)
return self

def build(self):
query = f”SELECT {self._select} FROM {self._from}”
if self._where:
query += ” WHERE ” + ” AND “.join(self._where)
return query

# Uso fluente
query = (QueryBuilder()
.select(“nome, email”)
.from_table(“usuarios”)
.where(“ativo = true”)
.where(“idade > 18”)
.build())

Padroes Estruturais

4. Adapter

Converte a interface de uma classe para outra que o cliente espera. Permite que classes incompativeis trabalhem juntas:

class StripePaymentAdapter:
def __init__(self, stripe_client):
self.stripe = stripe_client

def processar_pagamento(self, valor, cartao):
# Adapta para a interface do Stripe
return self.stripe.charges.create(
amount=int(valor * 100), # Stripe usa centavos
currency=”brl”,
source=cartao
)

class MercadoPagoPaymentAdapter:
def __init__(self, mp_client):
self.mp = mp_client

def processar_pagamento(self, valor, cartao):
# Adapta para a interface do MercadoPago
return self.mp.payment.create({
“transaction_amount”: valor,
“token”: cartao,
“payment_method_id”: “visa”
})

Ambos adaptadores tem a mesma interface (processar_pagamento), permitindo trocar provedores sem mudar o restante do codigo.

5. Decorator

Adiciona responsabilidades a objetos dinamicamente, sem alterar a classe original. Em Python, e elegantemente implementado com decoradores:

import time
import functools

def cache(ttl_seconds=300):
def decorator(func):
_cache = {}
@functools.wraps(func)
def wrapper(*args, **kwargs):
key = str(args) + str(kwargs)
if key in _cache:
resultado, timestamp = _cache[key]
if time.time() – timestamp < ttl_seconds:
return resultado
resultado = func(*args, **kwargs)
_cache[key] = (resultado, time.time())
return resultado
return wrapper
return decorator

@cache(ttl_seconds=60)
def buscar_usuario(user_id):
return db.query(f"SELECT * FROM usuarios WHERE id = {user_id}")

Padroes Comportamentais

6. Observer

Define dependencia um-para-muitos: quando um objeto muda, todos os dependentes sao notificados. Base de sistemas de eventos e pub/sub.

7. Strategy

Define uma familia de algoritmos intercambiaveis. O cliente escolhe qual usar em runtime. Muito usado para calculos de frete, desconto, imposto com regras que variam.

8. Command

Encapsula uma requisicao como objeto, permitindo undo/redo, filas de operacoes e log de acoes.

9. Template Method

Define o esqueleto de um algoritmo, delegando alguns passos para subclasses. A versao moderna usa composicao com funcoes ao inves de heranca.

10. Repository

Apesar de nao ser GoF original, e o padrao mais usado em aplicacoes modernas. Abstrai o acesso a dados, desacoplando a logica de negocio do banco de dados. Cada entidade tem seu repository com metodos como find_by_id, find_all, save, delete.

Tem um projeto em mente?

Somos especialistas em transformar ideias em produtos digitais. Apps, sites, automações e IA — vamos construir juntos.

Resposta rápida Orçamento sem compromisso +100 projetos entregues
Compartilhar: