Acesse o painel da sua conta

Não tem uma conta? Registrar

Entrar em contato

Visite também nosso site craftxp.com.br

  • img
  • img
  • img
  • img
  • img
  • img

Entre em contato

Design Patterns para Iniciantes: Entendendo os Padroes de Projeto de Forma Simples

Design Patterns para Iniciantes: Entendendo os Padroes de Projeto de Forma Simples

Se voce ja ouviu falar em Design Patterns (Padroes de Projeto) e ficou com a impressao de que e um assunto complexo e reservado apenas para desenvolvedores seniors, este artigo e para voce. Vamos desmistificar esse tema de forma simples, com analogias do dia a dia e exemplos praticos em Python.

O que sao Design Patterns?

Imagine que voce esta cozinhando. Voce pode inventar uma receita do zero a cada refeicao, ou pode usar receitas testadas e aprovadas — como a de um bolo de cenoura ou um arroz soltinho. Design Patterns sao exatamente isso: receitas comprovadas para problemas comuns de programacao.

Em termos tecnicos, um Design Pattern e uma solucao reutilizavel para um problema recorrente no desenvolvimento de software. Nao e um codigo pronto que voce copia e cola — e um conceito, um modelo que voce adapta para sua realidade.

💡 "Design Patterns sao plantas de construcao testadas para problemas comuns de software." — Gang of Four

A Origem: Gang of Four (GoF)

Tudo comecou em 1995, quando quatro autores — Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides — publicaram o livro "Design Patterns: Elements of Reusable Object-Oriented Software". Eles ficaram conhecidos como a Gang of Four (GoF) e catalogaram 23 padroes que ate hoje sao a base do design de software moderno.

Esses 23 padroes foram divididos em tres categorias, que veremos a seguir.

Por que usar Design Patterns?

  • Vocabulario comum: Quando um dev diz "vamos usar um Singleton aqui", todos entendem o que significa — sem precisar explicar o conceito do zero.
  • Solucoes testadas: Sao problemas que milhares de desenvolvedores ja enfrentaram antes. Nao invente a roda.
  • Codigo mais organizado: Os padroes incentivam boas praticas como baixo acoplamento e alta coesao.
  • Facilidade de manutencao: Um codigo que segue padroes conhecidos e mais facil de dar manutencao e de passar para outros devs.

As 3 Categorias de Design Patterns

Os 23 padroes se dividem em tres grupos, cada um resolvendo um tipo especifico de problema.

1. Padroes Criacionais

Os padroes criacionais lidam com a criacao de objetos. Eles abstraem o processo de instanciacao, tornando o sistema mais flexivel e independente de como os objetos sao criados.

Singleton

Problema: Voce precisa garantir que uma classe tenha apenas uma unica instancia em todo o sistema, com um ponto de acesso global.

Analogia: O presidente de um pais. So existe um presidente por vez. Nao importa quantas pessoas tentem "criar" um novo presidente — o cargo e unico.

Exemplo pratico: Conexao com banco de dados. Voce nao quer abrir uma nova conexao a cada operacao — quer reutilizar a mesma.

class ConexaoBanco:
    _instancia = None

    def __new__(cls):
        if cls._instancia is None:
            cls._instancia = super().__new__(cls)
            print("Nova conexao com o banco criada!")
        return cls._instancia

# Uso:
db1 = ConexaoBanco()
db2 = ConexaoBanco()
print(db1 is db2)  # True — mesmo objeto!

Factory Method

Problema: Voce precisa criar objetos, mas quer delegar a decisao de qual classe concreta instanciar para as subclasses.

Analogia: Uma fabrica de brinquedos. Voce pede um "carrinho" e a fabrica decide se produz um carrinho de plastico, de metal ou de madeira — voce so recebe o produto pronto.

class Notificacao:
    def enviar(self, msg):
        pass

class Email(Notificacao):
    def enviar(self, msg):
        print(f"Enviando e-mail: {msg}")

class SMS(Notificacao):
    def enviar(self, msg):
        print(f"Enviando SMS: {msg}")

def criar_notificacao(tipo):
    if tipo == "email":
        return Email()
    elif tipo == "sms":
        return SMS()
    raise ValueError("Tipo desconhecido")

# Uso:
notif = criar_notificacao("email")
notif.enviar("Bem-vindo!")

Builder

Problema: Voce precisa construir um objeto complexo passo a passo, com diferentes combinacoes de partes opcionais.

Analogia: Montar um hamburguer. Pao, carne, queijo, alface, tomate, molho — voce escolhe os ingredientes e a ordem.

class Pizza:
    def __init__(self):
        self.ingredientes = []

    def adicionar(self, item):
        self.ingredientes.append(item)
        return self

    def exibir(self):
        print(f"Pizza com: {', '.join(self.ingredientes)}")

# Uso:
pizza = Pizza()
pizza.adicionar("queijo").adicionar("calabresa")
pizza.exibir()

2. Padroes Estruturais

Os padroes estruturais tratam da composicao de classes e objetos. Eles mostram como montar estruturas maiores a partir de partes menores.

Adapter

Problema: Duas classes com interfaces incompativeis precisam trabalhar juntas.

Analogia: Um adaptador de tomada. Voce viaja para outro pais e precisa usar o seu carregador. O adaptador converte a tomada do pais para o formato que seu carregador aceita.

class TomadaAmericana:
    def voltagem(self):
        return 110

class TomadaBrasileira:
    def voltagem_220(self):
        return 220

class AdaptadorTomada:
    def __init__(self, tomada):
        self.tomada = tomada

    def voltagem(self):
        return self.tomada.voltagem_220() // 2

# Uso:
tomada_br = TomadaBrasileira()
adaptador = AdaptadorTomada(tomada_br)
print(f"{adaptador.voltagem()}V")  # 110V

Decorator

Problema: Voce precisa adicionar comportamentos a um objeto sem modificar sua classe.

Analogia: Um cafe. Voce comeca com um cafe simples, depois adiciona leite, chantilly, calda de chocolate — cada complemento "decora" o cafe base sem alterar o que ele e.

class Cafe:
    def custo(self):
        return 5
    def descricao(self):
        return "Cafe simples"

class ComLeite:
    def __init__(self, cafe):
        self.cafe = cafe
    def custo(self):
        return self.cafe.custo() + 2
    def descricao(self):
        return self.cafe.descricao() + ", leite"

# Uso:
meu_cafe = ComLeite(Cafe())
print(f"{meu_cafe.descricao()} — R${meu_cafe.custo()}")

Facade

Problema: Um sistema complexo com muitas classes e dependencias precisa de uma interface simplificada.

Analogia: O controle remoto da TV. Voce nao precisa entender os circuitos internos, a placa-mae, o transformador — voce so aperta "ligar" e "mudar canal".

class Motor:
    def ligar(self): print("Motor ligado")

class ArCondicionado:
    def ligar(self): print("Ar-condicionado ligado")

class Farol:
    def acender(self): print("Farois acesos")

class CarroFacade:
    def __init__(self):
        self.motor = Motor()
        self.ar = ArCondicionado()
        self.farol = Farol()

    def ligar_carro(self):
        self.motor.ligar()
        self.ar.ligar()
        self.farol.acender()
        print("Carro pronto para rodar!")

carro = CarroFacade()
carro.ligar_carro()

3. Padroes Comportamentais

Os padroes comportamentais tratam da comunicacao entre objetos. Eles definem como os objetos interagem, distribuem responsabilidades e se comunicam de forma flexivel.

Observer

Problema: Um objeto precisa notificar varios outros sobre mudancas em seu estado, sem acopla-los.

Analogia: Um canal no YouTube. Quando voce se inscreve, recebe notificacoes sempre que um novo video e publicado.

class CanalYouTube:
    def __init__(self):
        self.inscritos = []

    def inscrever(self, usuario):
        self.inscritos.append(usuario)

    def publicar_video(self, titulo):
        for usuario in self.inscritos:
            usuario.notificar(titulo)

class Usuario:
    def __init__(self, nome):
        self.nome = nome
    def notificar(self, video):
        print(f"{self.nome} recebeu: Novo video — {video}")

canal = CanalYouTube()
canal.inscrever(Usuario("Joao"))
canal.inscrever(Usuario("Maria"))
canal.publicar_video("Design Patterns para Iniciantes")

Strategy

Problema: Voce precisa permitir que diferentes algoritmos sejam trocados em tempo de execucao.

Analogia: Formas de pagamento no e-commerce. Voce escolhe se paga com cartao de credito, boleto ou PIX. O sistema processa de forma diferente para cada metodo.

class PagamentoCartao:
    def pagar(self, valor):
        print(f"Pago R${valor} no cartao de credito")

class PagamentoPIX:
    def pagar(self, valor):
        print(f"Pago R${valor} via PIX")

class Checkout:
    def __init__(self, estrategia):
        self.estrategia = estrategia

    def finalizar(self, valor):
        self.estrategia.pagar(valor)

checkout = Checkout(PagamentoPIX())
checkout.finalizar(150)

# Trocando a estrategia em tempo de execucao:
checkout.estrategia = PagamentoCartao()
checkout.finalizar(150)

Template Method

Problema: Voce tem um algoritmo com etapas fixas, mas algumas etapas podem variar. O template define a estrutura, as subclasses implementam os detalhes.

Analogia: Preparar bebidas quentes. Tanto o cafe quanto o cha seguem o mesmo processo: ferver agua, preparar o sabor, servir.

class BebidaQuente:
    def preparar(self):
        self.ferver_agua()
        self.adicionar_sabor()
        self.servir()

    def ferver_agua(self):
        print("Agua fervida a 100C")

    def adicionar_sabor(self):
        pass

    def servir(self):
        print("Servido na xicara")

class Cafe(BebidaQuente):
    def adicionar_sabor(self):
        print("Coado o po de cafe")

class Cha(BebidaQuente):
    def adicionar_sabor(self):
        print("Infusionado o saquinho de cha")

Cafe().preparar()
Cha().preparar()

Como Estudar Design Patterns?

  • Comece pelos mais comuns: Singleton, Factory, Observer e Strategy sao os mais usados no dia a dia.
  • Nao force o uso: o padrao certo surge naturalmente quando voce identifica o problema. Nao saia colocando padroes onde nao precisa.
  • Estude o problema, nao o padrao: entenda o problema primeiro. Quando ele aparecer no seu codigo, voce reconhecera o padrao automaticamente.
  • Pratique com projetos reais: refatore codigo legado aplicando padroes — e o melhor jeito de aprender.

Conclusao

Design Patterns nao sao um bicho de sete cabecas. Sao ferramentas que tornam seu codigo mais organizado, reutilizavel e facil de comunicar com outros desenvolvedores.

Pense neles como o vocabulario da boa programacao. Quanto mais padroes voce conhece, mais solucoes elegantes voce tem a disposicao para resolver problemas do dia a dia.

Comece praticando com os exemplos deste artigo, e aos poucos voce vai perceber que ja esta usando varios padroes sem nem perceber! 🚀

Para Aprofundar

  • Livro: Design Patterns: Elements of Reusable Object-Oriented Software (GoF)
  • Livro: Head First Design Patterns — abordagem mais didatica
  • Refactoring Guru (refactoring.guru) — site com explicacoes e exemplos em varias linguagens
Craft XP
Craft XP