¿Alguna vez te has quedado atascado intentando crear una función de undo por tu cuenta?
Es una función habitual que termina con un solo Ctrl+Z, pero trasladarla al código puede ser sorprendentemente complicada. Incluso en un proyecto de juguete parecido a Paint puedes pasar días con ella.
La conclusión es esta: la implementación de undo se divide, a grandes rasgos, en dos enfoques.
Uno es el patrón Command, que revierte las acciones realizadas; el otro es el patrón Memento, que guarda el estado completo anterior a una acción.
Ambos son válidos. La elección depende de cuándo y para qué uses cada uno. Hoy los compararemos con código.
Patrón Command — Envolver acciones en objetos
El patrón Command guarda en un único objeto qué se hizo.
Puedes verlo como un objeto que agrupa execute y undo.
Por ejemplo, si una acción consiste en introducir texto, defines de antemano en el mismo objeto su opuesta: borrar exactamente lo introducido.
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) }
}
Estos objetos Command se apilan uno tras otro.
Cuando llega Ctrl+Z, sacas el elemento superior y llamas a undo(). Eso es todo.
El patrón Command almacena acciones, no estado.
Patrón Memento — Guardar el estado como instantáneas
Memento adopta un enfoque completamente distinto.
En lugar de pensar cómo revertir cada acción, guardas todo el estado justo antes del cambio, como si hicieras una fotografía.
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 = "Hola"
let snapshot = editor.save() // Guardar la instantánea aquí
editor.content = "Hola"
editor.restore(snapshot)
print(editor.content)
// Salida: Hola
Cuando necesitas undo, sustituyes el estado por la instantánea guardada. Eso es todo.
Resulta cómodo no tener que escribir lógica de reversión para cada acción.
Pero también tiene una desventaja clara. Si el estado es grande, consume bastante memoria porque se copia completo cada vez.
Entonces, ¿cuál deberías usar?
He resumido en una tabla las diferencias que noté después de usar ambos.
| Criterio | Patrón Command | Patrón Memento |
|---|---|---|
| Elemento almacenado | Acción (execute/undo) | Instantánea del estado |
| Memoria | Ligero | Pesado si el estado es grande |
| Lógica de undo | Implementada manualmente para cada acción | Solo hay que restaurar |
| redo | Natural al desapilar | Posible con un array de instantáneas |
| Dónde encaja mejor | Editores, herramientas gráficas | Partidas guardadas, estado de formularios |
En una sola frase, sería así.
Si puedes definir claramente la acción inversa, usa Command; si te resulta más cómodo capturar todo el estado, usa Memento.
Cuándo usarlo y cuándo evitarlo
En la práctica, elijo según estos criterios.
- Los límites de las acciones son claros y también necesitas redo → Command. Los editores y las herramientas de dibujo son ejemplos típicos.
- El estado es pequeño y copiar instantáneas no supone un problema → Memento. Por ejemplo, entradas de formularios o restauración de valores de configuración.
- El estado es enorme, pero los cambios son locales → Evita Memento. Copiarlo todo cada vez puede agotar la memoria. Command es mejor.
- No se te ocurre la lógica de reversión → No fuerces Command; guardar instantáneas con Memento es más limpio.
En la práctica también se combinan. Se gestionan las acciones con Command y se guardan instantáneas Memento solo para las partes difíciles de revertir.
Así lo preguntan en las entrevistas
P. ¿Cuál es la diferencia entre los patrones Command y Memento?
Command encapsula una acción en un objeto y empareja execute con undo. Memento guarda el estado de un objeto como instantánea y después lo restaura. En otras palabras, la diferencia es si undo usa la operación inversa o la restauración del estado.
P. Si implementaras una pila de undo, ¿cuál elegirías?
Si los límites de las acciones están claros y quieres admitir redo de forma natural, elige Command. Si el estado es pequeño y escribir la lógica de reversión resulta engorroso, apilar instantáneas con Memento es más sencillo y seguro.
Te recomiendo implementar ambos patrones por tu cuenta al menos una vez. Leer los conceptos y ver cómo se apilan los objetos y cómo el estado retrocede con Ctrl+Z producen niveles de comprensión completamente distintos. Espero que este artículo te ayude a dar el primer paso.

