Você já travou ao tentar criar uma função de undo por conta própria?
É uma função comum que termina com um único Ctrl+Z, mas levá-la para o código pode ser surpreendentemente trabalhoso. Até em um projeto de brinquedo parecido com o Paint, é fácil passar dias nisso.
Indo direto ao ponto: a implementação de undo segue, em linhas gerais, duas abordagens.
Uma é o padrão Command, que desfaz as ações realizadas; a outra é o padrão Memento, que salva o estado completo anterior a uma ação.
As duas estão corretas. A escolha depende de quando e por que você usa cada uma. Hoje vamos compará-las com código.
Padrão Command — Encapsulando ações em objetos
O padrão Command coloca em um único objeto o que foi feito.
Pense nele como um objeto que combina execute e undo.
Por exemplo, se a ação for inserir texto, você define antecipadamente no mesmo objeto o oposto: apagar exatamente o que foi inserido.
protocol Command {
func execute()
func undo()
}
struct TypeCommand: Command {
let text: String
let editor: Editor
func execute() { editor.content += text }
func undo() { editor.content.removeLast(text.count) }
}
Esses objetos Command são empilhados um a um.
Quando chega um Ctrl+Z, basta retirar o item do topo e chamar undo(). É só isso.
O padrão Command armazena ações, não estado.
Padrão Memento — Salvando o estado como snapshots
O Memento segue uma abordagem completamente diferente.
Em vez de pensar em como desfazer cada ação, você salva o estado inteiro imediatamente antes da mudança, como se tirasse uma foto.
struct Memento { let content: String }
class Editor {
var content = ""
func save() -> Memento { Memento(content: content) }
func restore(_ m: Memento) { content = m.content }
}
let editor = Editor()
editor.content = "Olá"
let snapshot = editor.save() // Salvar snapshot aqui
editor.content = "Olá"
editor.restore(snapshot)
print(editor.content)
// Saída: Olá
Quando o undo for necessário, basta substituir o estado pelo snapshot salvo. É só isso.
É um alívio não precisar escrever a lógica de reversão para cada ação.
Mas a desvantagem também é clara. Se o estado for grande, ele consome bastante memória, porque é copiado por inteiro a cada vez.
Então, qual usar?
Organizei em uma tabela as diferenças que percebi depois de usar os dois.
| Critério | Padrão Command | Padrão Memento |
|---|---|---|
| O que é armazenado | Ação (execute/undo) | Snapshot do estado |
| Memória | Leve | Pesado quando o estado é grande |
| Lógica de undo | Implementada manualmente para cada ação | Basta restaurar |
| redo | Natural ao desempilhar | Possível com um array de snapshots |
| Onde se encaixa melhor | Editores, ferramentas gráficas | Saves de jogos, estado de formulários |
Resumindo em uma linha:
Se você consegue definir claramente a ação inversa, use Command; se for mais simples capturar o estado inteiro, use Memento.
Quando usar e quando evitar
Na prática, escolho com base nestes critérios.
- Os limites das ações são claros e redo também é necessário → Command. Editores e ferramentas de desenho são exemplos típicos.
- O estado é pequeno e copiar snapshots não pesa → Memento. Por exemplo, entradas de formulários e restauração de configurações.
- O estado é enorme, mas as mudanças são locais → Evite Memento. Copiar tudo a cada vez pode esgotar a memória. Command é melhor.
- Você não consegue imaginar a lógica de reversão → Não force o uso de Command; salvar snapshots com Memento é mais limpo.
No trabalho, também é comum combinar os dois. As ações são gerenciadas com Command, enquanto apenas as partes difíceis de desfazer recebem snapshots Memento.
É assim que perguntam em entrevistas
P. Qual é a diferença entre os padrões Command e Memento?
Command encapsula uma ação em um objeto e mantém execute e undo em par. Memento salva o estado de um objeto como snapshot e o restaura depois. Em outras palavras, a diferença está em desfazer pela operação inversa ou pela restauração do estado.
P. Se você implementasse uma pilha de undo, qual escolheria?
Se os limites das ações forem claros e você quiser oferecer redo naturalmente, escolha Command. Se o estado for pequeno e escrever a lógica de reversão der trabalho, empilhar snapshots com Memento é mais simples e seguro.
Recomendo implementar os dois padrões por conta própria pelo menos uma vez. Ler os conceitos e ver os objetos se acumulando na pilha e o estado voltando com Ctrl+Z produz níveis de compreensão completamente diferentes. Espero que este artigo ajude você a dar o primeiro passo.

