本文へスキップ
BecomeCoder

C#デザインパターンコース · 第1章 デザインパターン · レッスン12

振る舞い⑤:Visitor / Interpreter / Memento

ブラウザで完結

導入

GoFの締めくくり。Visitorは「データ構造を変えずに新しい操作を追加」、Interpreterは「独自の文法を解釈・評価」、Mementoは「状態を保存して後で復元(Undo)」します。

図解

flowchart LR
    S1["状態1"] -->|保存| M["Memento(スナップショット)"]
    S2["状態2(変更後)"] -->|Undo| M
    M -->|復元| S1

サンプル

// Memento: 状態を保存し、後で復元(Undo)する
var editor = new TextEditor();
editor.Type("こんにちは");
var saved = editor.Save();      // スナップショットを取る
editor.Type("(削除される)");
editor.Restore(saved);          // 保存時点に戻す
Console.WriteLine(editor.Text); // こんにちは

// Interpreter: 独自の簡単な式 "3 + 4" を解釈して評価
Console.WriteLine(Evaluate("3 + 4"));   // 7

class TextEditor
{
    public string Text { get; private set; } = "";
    public void Type(string s) => Text += s;
    public string Save() => Text;              // Memento(状態の複製)
    public void Restore(string memento) => Text = memento;
}

int Evaluate(string expr)
{
    var parts = expr.Split(' ');
    int a = int.Parse(parts[0]);
    int b = int.Parse(parts[2]);
    return parts[1] == "+" ? a + b : a - b;
}
  • Visitor: 要素側に「訪問者を受け入れる口」を作り、操作を外部クラス(訪問者)に追加できる
  • Interpreter: 独自の文法(式・ルール)を表現し評価する(電卓・クエリ言語等)
  • Memento: 内部状態のスナップショットを保存し、Undo/やり直しを実現する

演習

var game = new Game();
game.Score = 100;
var checkpoint = game.Save();
game.Score = 999;
game.Restore(checkpoint);
Console.WriteLine(game.Score);   // 100

// TODO: Score を Save() で保存し Restore() で復元できる Game クラスを定義してください
___
  • 期待される出力: 100
ヒント1を見る

Saveは現在のScoreを返し、Restoreは受け取った値をScoreに戻します

ヒント2を見る

class Game { public int Score; public int Save() => Score; public void Restore(int m) => Score = m; }

まとめ

  • Visitorはデータ構造を変えず操作を追加する
  • Interpreterは独自文法を解釈・評価する
  • Mementoは状態を保存し復元(Undo)する

次回: 23パターンの実践的な使い分けを整理します。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。