Aller au contenu principal

Pattern Memento

Capturez l'état d'un objet sous forme de snapshot pour pouvoir le restaurer plus tard sans exposer ses détails internes.


Le Problème​

Vous construisez un éditeur photo. Les utilisateurs appliquent des filtres : luminosité, contraste, saturation, flou, sépia. Ils veulent annuler, mais pas étape par étape : ils veulent cliquer sur n'importe quel état précédent et y revenir instantanément.

L'approche naïve :

let filterHistory: FilterState[] = [];
let currentIndex = 0;

function applyFilter(filter: string, value: number) {
canvas.apply(filter, value);
// Manual snapshot management everywhere
filterHistory = filterHistory.slice(0, currentIndex + 1);
filterHistory.push(captureState(canvas));
currentIndex++;
}

function jumpTo(index: number) {
currentIndex = index;
canvas.restore(filterHistory[index]); // hope the index is valid
}

La logique d'historique est mélangée avec la logique des filtres. Pas de miniatures, pas de métadonnées, pas de sécurité.


La Solution​

Séparez la gestion de l'historique de la logique métier. Chaque changement d'état crée un snapshot automatiquement :

import { createHistory } from "@pithos/core/eidos/memento/memento";

interface PhotoState {
brightness: number;
contrast: number;
saturation: number;
blur: number;
sepia: number;
thumbnail: string; // base64 preview
}

const history = createHistory<PhotoState>({
brightness: 100, contrast: 100, saturation: 100, blur: 0, sepia: 0,
thumbnail: captureThumb(canvas),
});

function applyFilter(filter: keyof PhotoState, value: number) {
const current = history.current();
const next = { ...current, [filter]: value, thumbnail: captureThumb(canvas) };
history.push(next);
}

// Jump to any snapshot directly
const snapshots = history.history(); // all snapshots with timestamps
// Click snapshot #3 → undo until we reach it

L'historique est automatique. Chaque snapshot inclut une miniature pour la navigation visuelle. Contrairement à Command (qui stocke des opérations nommées comme "augmenter luminosité +10"), Memento stocke l'état visuel complet : ce que vous voyez est ce que vous restaurez.


Démo​

Un éditeur photo où vous appliquez des filtres (luminosité, contraste, saturation, flou, sépia). Chaque changement crée un snapshot avec une miniature. Le panneau Historique vous permet de sauter à n'importe quel état directement, pas étape par étape. Contrairement à Command (opérations nommées), Memento capture des snapshots visuels de l'état complet.

Code
/**
* Memento pattern: photo history using createHistory.
*/

import { createHistory } from "@pithos/core/eidos/memento/memento";
import type { PhotoState } from "./types";

export function createPhotoHistory(initial: PhotoState) {
return createHistory<PhotoState>(initial);
}
Result

Analogie​

Un point de sauvegarde dans un jeu vidéo. Le jeu capture votre état exact : position, inventaire, santé, progression. Plus tard, vous pouvez restaurer ce moment précis. Le fichier de sauvegarde est le memento.


Quand l'Utiliser​

  • Implémenter le undo/redo avec des snapshots visuels de l'état
  • Créer des points de sauvegarde ou des checkpoints
  • L'état est peu coûteux à copier (petits objets, données immuables)
  • Les utilisateurs doivent pouvoir sauter à n'importe quel état précédent, pas seulement reculer d'un pas
Memento vs Command

Les deux supportent le undo/redo. Memento stocke des snapshots d'état : idéal quand l'état est petit et que vous voulez un historique visuel. Command stocke des actions avec des opérations inverses : idéal quand l'état est volumineux mais les opérations sont réversibles. L'éditeur photo utilise Memento parce que vous voulez voir des miniatures de chaque état, pas une liste de "luminosité +10".


Quand NE PAS l'Utiliser​

Si votre état est volumineux (un document complet, une scène 3D complexe), stocker des snapshots à chaque changement coûte cher. Utilisez Command à la place, qui ne stocke que le delta.


API​

  • createHistory — Créer un historique d'état avec support undo/redo