Skip to content

Instantly share code, notes, and snippets.

@rg3915
Created November 7, 2024 02:00
Show Gist options
  • Save rg3915/8dce4121fc2e5e27a7e8beb2bfcb28fd to your computer and use it in GitHub Desktop.
Save rg3915/8dce4121fc2e5e27a7e8beb2bfcb28fd to your computer and use it in GitHub Desktop.
template method x state machine - chatGPT

O Template Method é um padrão de projeto comportamental que define o esqueleto de um algoritmo em um método de uma classe base, permitindo que as subclasses substituam etapas específicas do algoritmo sem alterar a estrutura geral. Em outras palavras, o Template Method fornece uma forma de definir o fluxo de execução de um processo, enquanto delega a implementação de detalhes específicos para as subclasses.

Exemplo de Template Method em Python

Imagine que você tenha um sistema para processar diferentes tipos de documentos, e cada documento pode ter etapas específicas de processamento, mas o fluxo geral é o mesmo:

from abc import ABC, abstractmethod

class ProcessadorDocumento(ABC):
    def processar(self):
        self.abrir_documento()
        self.validar_documento()
        self.processar_conteudo()
        self.fechar_documento()

    def abrir_documento(self):
        print("Documento aberto.")

    @abstractmethod
    def validar_documento(self):
        pass

    @abstractmethod
    def processar_conteudo(self):
        pass

    def fechar_documento(self):
        print("Documento fechado.")

class ProcessadorPDF(ProcessadorDocumento):
    def validar_documento(self):
        print("Validando documento PDF.")

    def processar_conteudo(self):
        print("Processando conteúdo do PDF.")

class ProcessadorWord(ProcessadorDocumento):
    def validar_documento(self):
        print("Validando documento Word.")

    def processar_conteudo(self):
        print("Processando conteúdo do Word.")

# Uso
processador = ProcessadorPDF()
processador.processar()

processador = ProcessadorWord()
processador.processar()

Nesse exemplo, ProcessadorDocumento define o método processar, que é o template method, com o esqueleto do algoritmo. As subclasses ProcessadorPDF e ProcessadorWord implementam as etapas específicas, validar_documento e processar_conteudo.

Diferença para Máquina de Estado

Uma Máquina de Estado é um conceito diferente, onde um sistema é modelado como um conjunto de estados finitos e transições entre esses estados. A máquina de estado é útil para representar o comportamento de um sistema que pode mudar de estado em resposta a eventos ou condições.

Comparando os Dois Conceitos:

  • Template Method:

    • É focado em definir o fluxo de execução de um algoritmo, deixando que subclasses implementem detalhes específicos.
    • Permite uma estrutura de código comum para algoritmos que têm a mesma sequência de etapas, mas com implementação diferente em partes específicas.
    • Não muda de "estado" no sentido de um sistema reativo, mas sim define um processo linear.
  • Máquina de Estado:

    • É usada para modelar sistemas que precisam responder a diferentes eventos ou inputs e mudar de estado como resultado.
    • Ideal para representar sistemas com comportamentos mutáveis e interdependentes, como um ciclo de vida de objeto (por exemplo, máquina de venda automática, sistema de autorização de usuário).
    • Foca em transições e regras de como o sistema deve mudar de um estado para outro, com cada estado podendo ter suas próprias regras e comportamentos.

Exemplo de Máquina de Estado:

class MaquinaDeEstados:
    def __init__(self):
        self.estado_atual = 'inicial'

    def evento(self, evento):
        if self.estado_atual == 'inicial' and evento == 'comecar':
            self.estado_atual = 'em_progresso'
            print("Mudou para o estado: em_progresso")
        elif self.estado_atual == 'em_progresso' and evento == 'finalizar':
            self.estado_atual = 'finalizado'
            print("Mudou para o estado: finalizado")
        else:
            print("Evento não permitido.")

# Uso
maquina = MaquinaDeEstados()
maquina.evento('comecar')
maquina.evento('finalizar')

Neste exemplo, uma máquina de estado muda de 'inicial' para 'em_progresso' e, depois, para 'finalizado', dependendo do evento recebido.

Resumindo:

  • Use Template Method para definir algoritmos com passos fixos e personalizáveis.
  • Use Máquina de Estado para modelar sistemas que têm estados diferentes e precisam reagir a eventos, com transições controladas entre estados.

Vou criar um exemplo simples de uma aplicação que utiliza o Template Method no front-end para exibir uma estrutura de processo com AlpineJS e estilização básica com PicoCSS. Esse exemplo simula um processo onde o usuário segue etapas (como um "wizard" de passos).

Exemplo: Processo de Cadastro com Template Method

Neste exemplo, criamos uma estrutura de um processo de várias etapas, onde a lógica geral é mantida no código AlpineJS, e as etapas específicas são renderizadas dinamicamente.

Estrutura HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Template Method com AlpineJS e PicoCSS</title>
    <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@1.*/css/pico.min.css">
    <script src="//unpkg.com/alpinejs" defer></script>
</head>
<body>
    <main x-data="cadastroProcesso()">
        <header>
            <h1>Processo de Cadastro</h1>
        </header>

        <section>
            <template x-if="etapaAtual <= etapas.length">
                <div>
                    <h2 x-text="`Etapa ${etapaAtual}: ${etapas[etapaAtual - 1].titulo}`"></h2>
                    <p x-text="etapas[etapaAtual - 1].descricao"></p>
                </div>
            </template>
            
            <template x-if="etapaAtual > etapas.length">
                <div>
                    <h2>Cadastro Completo!</h2>
                    <p>Obrigado por concluir todas as etapas.</p>
                </div>
            </template>
        </section>

        <footer>
            <button type="button" x-show="etapaAtual > 1" @click="voltar()">Voltar</button>
            <button type="button" x-show="etapaAtual <= etapas.length" @click="avancar()">Avançar</button>
        </footer>
    </main>

    <script>
        function cadastroProcesso() {
            return {
                etapaAtual: 1,
                etapas: [
                    { titulo: 'Informações Pessoais', descricao: 'Preencha suas informações pessoais.' },
                    { titulo: 'Endereço', descricao: 'Preencha seu endereço.' },
                    { titulo: 'Confirmação', descricao: 'Revise suas informações e confirme.' }
                ],
                avancar() {
                    if (this.etapaAtual <= this.etapas.length) {
                        this.etapaAtual++;
                    }
                },
                voltar() {
                    if (this.etapaAtual > 1) {
                        this.etapaAtual--;
                    }
                }
            };
        }
    </script>
</body>
</html>

Explicação:

  1. HTML: Estruturamos a página com elementos como <header>, <section>, e <footer>, onde a navegação entre etapas é exibida.
  2. PicoCSS: É usado para estilizar os elementos de forma simples e responsiva.
  3. AlpineJS:
    • O componente cadastroProcesso() define o processo de várias etapas, que se assemelha ao Template Method, onde a estrutura geral (avançar, voltar) é mantida, mas o conteúdo de cada etapa (etapas) é customizável.
    • A navegação entre etapas é gerenciada pelos métodos avancar() e voltar().

Como Funciona:

  • A variável etapaAtual mantém a etapa que está sendo visualizada.
  • A variável etapas contém as informações de cada etapa, com titulo e descricao.
  • O botão "Avançar" move para a próxima etapa, e o botão "Voltar" permite retornar à etapa anterior.
  • Quando todas as etapas são concluídas, é exibida uma mensagem de finalização.

Possíveis Melhorias:

  • Adicionar validação de campos em cada etapa.
  • Incluir animações para transições entre as etapas.
  • Tornar o processo mais dinâmico, como carregar etapas de uma API.

Esse exemplo simples ajuda a entender como criar um fluxo de processo reutilizável usando AlpineJS e manter uma aparência clean com PicoCSS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment