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.
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
.
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.
-
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.
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.
- 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).
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.
<!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>
- HTML: Estruturamos a página com elementos como
<header>
,<section>
, e<footer>
, onde a navegação entre etapas é exibida. - PicoCSS: É usado para estilizar os elementos de forma simples e responsiva.
- 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()
evoltar()
.
- O componente
- A variável
etapaAtual
mantém a etapa que está sendo visualizada. - A variável
etapas
contém as informações de cada etapa, comtitulo
edescricao
. - 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.
- 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.