Memento
Publié le 23 Mai 2025Memento (mémento en français) est un design pattern comportemental qui permet de capturer et de stocker l’état interne d’un objet sans enfreindre le principe d’encapsulation et de manière à le restaurer ultérieurement.
Principe
Exemples d’utilisation de Memento
Annuler les modifications dans un formulaire complexe
Système de configuration avec sauvegarde et restauration d’états
Points d’attentions
Implémenter un Memento
L’originator
Le Memento
Le Caretaker
Exemple d'utilisation de Memento en Go
package usersettings
// Memento Interface ou alias de memento exporté
type Memento any // Alias, seul le package connaît son contenu
// UserSettings Originator
type UserSettings struct {
theme string
language string
notificationsEnabled bool
}
func NewUserSettings(theme, language string, notificationsEnabled bool) *UserSettings {
return &UserSettings{theme, language, notificationsEnabled}
}
func (s *UserSettings) Save() Memento {
return &settingsMemento{
theme: s.theme,
language: s.language,
notificationsEnabled: s.notificationsEnabled,
}
}
func (s *UserSettings) Restore(m Memento) {
if mem, ok := m.(*settingsMemento); ok {
s.theme = mem.theme
s.language = mem.language
s.notificationsEnabled = mem.notificationsEnabled
}
}
func (s *UserSettings) Theme() string { return s.theme }
func (s *UserSettings) Language() string { return s.language }
func (s *UserSettings) NotificationsEnabled() bool { return s.notificationsEnabled }
// Memento non exporté
type settingsMemento struct {
theme string
language string
notificationsEnabled bool
}
package main
import (
"fmt"
"designpatterns/memento/usersettings"
)
type SettingsCaretaker struct {
memento usersettings.Memento
}
func main() {
settings := usersettings.NewUserSettings("light", "en", true)
caretaker := &SettingsCaretaker{}
// Sauvegarde de l'état initial
caretaker.memento = settings.Save()
fmt.Println("Avant modification :")
printSettings(settings)
// Modifications de l'utilisateur
settings.Restore(usersettings.NewUserSettings("dark", "fr", false).Save())
fmt.Println("Après modification :")
printSettings(settings)
// Restauration de l'état précédent
settings.Restore(caretaker.memento)
fmt.Println("Après restauration :")
printSettings(settings)
}
func printSettings(s *usersettings.UserSettings) {
fmt.Printf("Thème: %s, Langue: %s, Notifications activées: %v\n",
s.Theme(), s.Language(), s.NotificationsEnabled())
}
Le même exemple en PHP
namespace Practice\DesignPatterns\Memento;
class UserSettings
{
private string $theme;
private string $language;
private bool $notificationsEnabled;
public function __construct(string $theme, string $language, bool $notificationsEnabled)
{
$this->theme = $theme;
$this->language = $language;
$this->notificationsEnabled = $notificationsEnabled;
}
public function save(): SettingsMemento
{
return new SettingsMemento($this->theme, $this->language, $this->notificationsEnabled);
}
public function restore(SettingsMemento $memento): void
{
$this->theme = $memento->getTheme();
$this->language = $memento->getLanguage();
$this->notificationsEnabled = $memento->isNotificationsEnabled();
}
public function __toString(): string
{
return "Theme: {$this->theme}, Langue: {$this->language}, Notifications: " . ($this->notificationsEnabled ? "activées" : "désactivées");
}
}
namespace Practice\DesignPatterns\Memento;
class SettingsMemento
{
public function __construct(
private string $theme,
private string $language,
private bool $notificationsEnabled
) {}
public function getTheme(): string { return $this->theme; }
public function getLanguage(): string { return $this->language; }
public function isNotificationsEnabled(): bool { return $this->notificationsEnabled; }
}
namespace Practice\DesignPatterns\Memento;
class SettingsCaretaker
{
public ?SettingsMemento $memento = null;
}
declare(strict_types=1);
use Practice\DesignPatterns\Memento\SettingsCaretaker;
use Practice\DesignPatterns\Memento\UserSettings;
require "./vendor/autoload.php";
// Exemple d'utilisation
$settings = new UserSettings("light", "en", true);
$caretaker = new SettingsCaretaker();
$caretaker->memento = $settings->save(); // sauvegarde de l'état initial
// Modifications par l'utilisateur
$settings = new UserSettings("dark", "fr", false);
echo "Paramètres modifiés : $settings\n";
// Annulation
$settings->restore($caretaker->memento);
echo "Paramètres restaurés : $settings\n";