Mementoパターンとは|GoFデザインパターンの解説

デザインパターンとは IT技術
IT技術

本記事では、GoFデザインパターンの一つであるMementoパターンについて詳しく解説します。

Mementoパターンは、オブジェクトの状態を保存し、必要に応じてその状態を復元するためのパターンです。

この記事では、Mementoパターンの定義、利用シーン、Java、C++、C#での実装サンプルを紹介します。

Mementoパターンとは

Mementoパターンは、オブジェクトの内部状態を保存し、その後にその状態を復元できるようにする設計パターンです。

このパターンは、オブジェクトの内部状態を外部から隠蔽しつつ、状態の保存と復元を実現します。

これにより、オブジェクトの履歴管理や状態管理が容易になり、特定のタイミングでの状態に戻す機能が実装できます。

利用シーン

Mementoパターンは、主に以下のようなシーンで利用されます。

Point
  • アンドゥ機能の実装
  • 状態管理を必要とするゲームやシミュレーション
  • 一時的にシステムの状態を保存して、復元する必要があるアプリケーション

Mementoパターンの使い方

Mementoパターンを使う際には、3つの主要な要素が登場します。

Point
  • Memento(記録):オブジェクトの内部状態を保存する役割を担います。
  • Originator(発起人):保存される状態を持つオブジェクトです。必要に応じてMementoを使って状態を復元します。
  • CareTaker(管理者):Mementoの保存や復元を管理する役割を担いますが、Mementoの詳細な実装には関与しません。

クラス構造

Mementoパターンを使用するクラス構造は以下のようになります

Point
  • Mementoクラス: 保存された状態を保持し、Originatorからその状態を取得・設定されます。
  • Originatorクラス: 保存されるオブジェクトであり、Mementoを利用して自らの状態を保存・復元します。
  • CareTakerクラス: 複数のMementoを保持し、Originatorが状態を復元する際に必要なMementoを提供します。

Mementoパターン実装サンプル

ここでは、Mementoパターンの実装例をJava、C++、C#のそれぞれの言語で紹介します。

JavaでのMementoパターン実装

以下は、JavaでのMementoパターンの実装例です。

class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}

class CareTaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento state) {
        mementoList.add(state);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}

public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        CareTaker careTaker = new CareTaker();

        originator.setState("State #1");
        careTaker.add(originator.saveStateToMemento());

        originator.setState("State #2");
        careTaker.add(originator.saveStateToMemento());

        originator.setState("State #3");

        System.out.println("Current State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(0));
        System.out.println("First saved State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        System.out.println("Second saved State: " + originator.getState());
    }
}

C++でのMementoパターン実装

以下は、C++でのMementoパターンの実装例です。

<pre><code>
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class Memento {
private:
    string state;
public:
    Memento(string state) : state(state) {}
    string getState() {
        return state;
    }
};

class Originator {
private:
    string state;
public:
    void setState(string state) {
        this->state = state;
    }

    string getState() {
        return state;
    }

    Memento saveStateToMemento() {
        return Memento(state);
    }

    void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
};

class CareTaker {
private:
    vector<Memento> mementoList;
public:
    void add(Memento state) {
        mementoList.push_back(state);
    }

    Memento get(int index) {
        return mementoList.at(index);
    }
};

int main() {
    Originator originator;
    CareTaker careTaker;

    originator.setState("State #1");
    careTaker.add(originator.saveStateToMemento());

    originator.setState("State #2");
    careTaker.add(originator.saveStateToMemento());

    originator.setState("State #3");

    cout << "Current State: " << originator.getState() << endl;
    originator.getStateFromMemento(careTaker.get(0));
    cout << "First saved State: " << originator.getState() << endl;
    originator.getStateFromMemento(careTaker.get(1));
    cout << "Second saved State: " << originator.getState() << endl;

    return 0;
}

C#でのMementoパターン実装

以下は、C#でのMementoパターンの実装例です。

using System;
using System.Collections.Generic;

class Memento {
    public string State { get; private set; }

    public Memento(string state) {
        this.State = state;
    }
}

class Originator {
    public string State { get; set; }

    public Memento SaveStateToMemento() {
        return new Memento(State);
    }

    public void GetStateFromMemento(Memento memento) {
        State = memento.State;
    }
}

class CareTaker {
    private List<Memento> mementoList = new List<Memento>();

    public void Add(Memento state) {
        mementoList.Add(state);
    }

    public Memento Get(int index) {
        return mementoList[index];
    }
}

class MementoPatternDemo {
    static void Main(string[] args) {
        Originator originator = new Originator();
        CareTaker careTaker = new CareTaker();

        originator.State = "State #1";
        careTaker.Add(originator.SaveStateToMemento());

        originator.State = "State #2";
        careTaker.Add(originator.SaveStateToMemento());

        originator.State = "State #3";
        Console.WriteLine("Current State: " + originator.State);

        originator.GetStateFromMemento(careTaker.Get(0));
        Console.WriteLine("First saved State: " + originator.State);

        originator.GetStateFromMemento(careTaker.Get(1));
        Console.WriteLine("Second saved State: " + originator.State);
    }
}

まとめ

Mementoパターンは、オブジェクトの状態を保存し、必要に応じて復元するための有効な手段を提供します。

アンドゥ機能や状態管理が必要なアプリケーションにおいて、その実装が求められる場面が多く、Java、C++、C#などの多くのプログラミング言語で応用が可能です。

ぜひ、このパターンを活用して、柔軟な状態管理を実現してみてください。

タイトルとURLをコピーしました