memento パターン(英: Memento pattern、日本: メメント パターン)はソフトウェアのデザインパターンの一つで、オブジェクトを以前の状態に(ロールバックにより)戻す能力を提供する。
memento パターンは二つのオブジェクトによって用いられる。'originator'と'caretaker' である。'originator' は内部状態を持つオブジェクトである。caretaker は originator に何らかの操作を行うが、その操作の結果を元に戻す機能を持たせたいとする。まず caretaker は操作を行う前に、originator へ現状の memento を要求して得る。その後、任意の操作を行う。操作前の状態に復元するには、先程 得た memento を originator に渡す。memento 自体は、不透明オブジェクト
( caretaker が変更してはいけないもの) である。このパターンを使う場合、originator が他のオブジェクトやリソースを変更してしまうかどうか注意が要る。memento パターンは単一のオブジェクトに対して働くためである。memento パターンの古典的な例として、擬似乱数発生器や、有限オートマトンの状態などがある。 以下の Java プログラムは、 Memento パターンを "undo" に使った場合を示す。import java.util.*; class Originator { private String state; /* メモリを消費する多数の private のデータで状態に関係しないものは保存されるべきでない。 * memento は小さなオブジェクトであるべき */ public void set(String state) { System.out.println("Originator: Setting state to "+state); this.state = state; } public Object saveToMemento() { System.out.println("Originator: Saving to Memento."); return new Memento(state); } public void restoreFromMemento(Object m) { if (m instanceof Memento) { Memento memento = (Memento)m; state = memento.getSavedState(); System.out.println("Originator: State after restoring from Memento: "+state); } } private static class Memento { private String state; public Memento(String stateToSave) { state = stateToSave; } public String getSavedState() { return state; } }} class Caretaker { private List<Object> savedStates = new ArrayList<Object>(); public void addMemento(Object m) { savedStates.add(m); } public Object getMemento(int index) { return savedStates.get(index); }} class MementoExample { public static void main(String[] args) { Caretaker caretaker = new Caretaker(); Originator originator = new Originator(); originator.set("State1"); originator.set("State2"); caretaker.addMemento( originator.saveToMemento() ); originator.set("State3"); caretaker.addMemento( originator.saveToMemento() ); originator.set("State4"); originator.restoreFromMemento( caretaker.getMemento(1) ); }} 出力:Originator: Setting state to State1Originator: Setting state to State2Originator: Saving to Memento.Originator: Setting state to State3Originator: Saving to Memento.Originator: Setting state to State4Originator: State after restoring from Memento: State3 以下の Ruby プログラムで同じパターンを示す。#!/usr/bin/env ruby -KUrequire 'rubygems'require 'spec'class Originator class Memento def initialize(state) # Originator の元の状態を壊しても、この Memento オブジェクトが初回以降の restore で # 破壊されないよう dup が必要 @state = state.dup end def state # Originator の元の状態を壊しても、この Memento オブジェクトが二度目の restore で # 破壊されないよう dup が必要 @state.dup end end attr_accessor :state # メモリに巨大なデータが多数あり、state から再構成可能であるように見せる def save_to_memento Memento.new(@state) end def restore_from_memento(m) @state = m.state endendclass Caretaker < Array; enddescribe Originator do before(:all) do @caretaker = Caretaker.new @originator = Originator.new @originator.state = "State1" end it "should have original state" do @originator.state.should == 'State1' end it "should update state" do @originator.state = "State2" @originator.state.should == 'State2' end it "should save memento" do @caretaker << @originator.save_to_memento @caretaker.size.should == 1 end it "should update state after save to memento" do @originator.state = "State3" @originator.state.should == 'State3' end it "should save to memento again" do @caretaker << @originator.save_to_memento @caretaker.size.should == 2 end it "should update state after save to memento again" do @originator.state = "State4"; @originator.state.should == 'State4' end it "should restore to original save point" do @originator.restore_from_memento @caretaker[0] @originator.state.should == 'State2' end it "should restore to second save point" do @originator.restore_from_memento @caretaker[1] @originator.state.should == 'State3' end it "should restore after pathological munging of restored state" do @originator.state[-1] = '5' @originator.state.should == 'State5' @originator.restore_from_memento @caretaker[1] @originator.state.should == 'State3' end it "should restore after pathological munging of original state" do @originator.state = "State6" @originator.state.should == 'State6' @caretaker << @originator.save_to_memento @originator.state[-1] = '7' @originator.state.should == 'State7' @originator.restore_from_memento @caretaker[2] @originator.state.should == 'State6' endend
Memento パターンの例
Java
Ruby
関連項目
Facade パターン
永続データ構造
外部リンク
⇒Description by Matthew Heaney
⇒Memento UML Class Diagram with C# and .NET code samples
表
話
編
歴
デザインパターン
GoFによる23種のパターン
生成に関するパターン
Abstract factory
Builder
Factory method
Prototype
Singleton
構造に関するパターン
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
振る舞いに関するパターン
Chain of responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template method
Visitor
並行性に関するパターン
Active object(英語版)
Balking(英語版)
Double-checked locking(英語版)
Event-based asynchronous(英語版)
Guarded suspension(英語版)
Join(英語版)
ロック
モニタ
Proactor(英語版)
Reactor
Readers?writer lock(英語版)
Scheduler(英語版)
Thread pool(英語版)
スレッド局所記憶
アーキテクチャに関するパターン
Front Controller(英語版)
Interceptor(英語版)
MVC
MVVM
多層アーキテクチャ
Specification(英語版)
出版-購読型モデル
Naked objects(英語版)
Service Locator(英語版)
Active Record
Identity map(英語版)
Data Access Object
Data Transfer Object
その他のパターン
依存性の注入 (DI)
遅延読み込み
モックオブジェクト
Null object(英語版)
Object pool(英語版)
Servant(英語版)
Type tunnel(英語版)
関連する人々
ギャング・オブ・フォー
エーリヒ・ガンマ
リチャード・ヘルム
ラルフ・ジョンソン
ジョン・ブリシディース
クリストファー・アレグザンダー
グラディ・ブーチ
ケント・ベック
ウォード・カニンガム
マーティン・ファウラー