メインコンテンツまでスキップ

🧪️ Undo/Redo を実装したい

✅ 背景と課題

フォームやエディタ、GUI 操作などで「直前の状態に戻す(Undo)」「やり直す(Redo)」機能を求められることがある。
このような機能を場当たり的に実装すると、状態の差分を手動で保存したり、処理の分岐が増えたりしてコードが煩雑になりがち。

特に次のような問題が起こる:

  • 変更操作の履歴が記録されていない
  • 「元に戻す」処理と「やり直す」処理が非対称でテストしづらい
  • 状態と操作がバラバラに扱われており、拡張やデバッグが困難

✅ 解決の方向性と適用パターン

操作を Command パターンで「コマンドオブジェクト」として記録し、
状態を Memento パターンで「スナップショット」として保存・復元できるようにする。

関心事使用パターン
操作の履歴管理・取り消しCommand
状態の保存と復元Memento

これにより、「操作の記録」と「状態の復元」が役割分担され、
Undo/Redo の処理が一貫した設計で実現できる。

✅ パターンの連携構成

要素実装例
実行・取り消し可能な操作EditCommand, InsertCommand
状態の保存EditorMemento
状態管理者Editor(Memento の Originator)
操作履歴の管理者HistoryManager(Invoker)

操作はコマンドとして抽象化され、各コマンドは実行時に Memento を保存することで、
いつでも状態を巻き戻せる構造となる。

✅ UML クラス図

✅ 解説

この設計では、EditCommand などの各操作を Command として扱い、
実行前に Editor の状態を EditorMemento として保存する。

HistoryManager はコマンドとスナップショットを履歴として管理し、
Undo/Redo 操作に応じて適切に処理と状態を巻き戻す。

この構成により:

  • 各コマンドが自律的に取り消しをサポートできる
  • 状態と操作が明確に分離される
  • 複雑な状態復元処理が簡潔に管理できる

✅ 実務での利点と適用例

  • ✅ テキストエディタや画像編集ツールなどの Undo/Redo に対応
  • ✅ 状態を保持したままロールバック可能なフォームやトランザクション制御
  • ✅ 操作ログと状態履歴を分離できるため、テストしやすくデバッグもしやすい

✅ まとめ

  • Command で操作の履歴をオブジェクトとして管理
  • Memento で状態のスナップショット保存と復元を実現
  • 両者を組み合わせることで、Undo/Redo を安全かつ柔軟に実装可能
  • ユーザー操作の信頼性と UX 向上に寄与する設計構造となる

特に「一連の変更をやり直す」ような GUI 操作において、この構成は保守性・拡張性の高い実装手段となる。