1. パターンの意図
メメント(Memento)パターン は、
オブジェクトの状態を保存し、後で復元できるようにする デザインパターンです。
解決する問題
- ゲームの「セーブ/ロード」のように、ある時点の状態を戻したい
- Undo / Redo 機能を実装したい
- 内部状態をカプセル化したまま保存・復元したい
ポイント
- Originator:状態を持つオブジェクト。スナップショットを作成/復元する
- Memento:保存される状態(外部から中身は見えない)
- Caretaker:Memento を管理し、必要に応じて復元を依頼する
2. UML 図
3. Flutter / Dart 実装例
Memento
class Memento {
final String state;
Memento(this.state);
}
Originator
class Originator {
String _state = '';
void setState(String state) {
print(" Setting state to $state");
_state = state;
}
String getState() => _state;
Memento save() => Memento(_state);
void restore(Memento memento) {
_state = memento.state;
print("State restored to $_state");
}
}
Caretaker
class Caretaker {
final List<Memento> _history = [];
void addMemento(Memento memento) => _history.add(memento);
Memento? getMemento(int index) {
if (index < 0) {
return null;
}
if (_history.length > index) {
return _history[index];
}
return null;
}
}
利用例
void main() {
var originator = Originator();
var caretaker = Caretaker();
originator.setState("State 1");
caretaker.addMemento(originator.save());
originator.setState("State 2");
caretaker.addMemento(originator.save());
originator.setState("State 3");
originator.restore(caretaker.getMemento(0)); // State 1 に戻る
}
4. Android / Kotlin 実装例
Memento
data class Memento(val state: String)
Originator
class Originator {
private var state: String = ""
fun setState(state: String) {
println("Setting state to $state")
this.state = state
}
fun getState(): String = state
fun save(): Memento = Memento(state)
fun restore(memento: Memento) {
state = memento.state
println("State restored to $state")
}
}
Caretaker
class Caretaker {
private val history = mutableListOf<Memento>()
fun addMemento(m: Memento) = history.add(m)
fun getMemento(index: Int): Memento?{
if(index<0){
return null;
}
if(history.size<=index){
return null;
}
return history[index]
}
}
利用例
fun main() {
val originator = Originator()
val caretaker = Caretaker()
originator.setState("State 1")
caretaker.addMemento(originator.save())
originator.setState("State 2")
caretaker.addMemento(originator.save())
originator.setState("State 3")
val memento=caretaker.getMemento(0)
if(memento!=null){
originator.restore(memento)// State 1 に戻る
}
}
5. 実務ユースケース
- テキストエディタの Undo / Redo
- 画面フォーム入力のスナップショット保存
- ゲームのセーブ/ロード
- IDE やエディタの Undo/Redo
- アプリの状態管理(フォーム、画面遷移)
- DB トランザクションのロールバック
6. メリット / デメリット
メリット
- 状態を保存・復元できる
- 内部構造を外部に公開せずにスナップショット可能
- Undo/Redo やセーブ機能に適用しやすい
デメリット
- 状態を大量に保存するとメモリ消費が大きい
- 状態管理ロジックが複雑化することもある
まとめ
- Memento パターンは「状態を保存し、後で復元できる仕組み」
- Flutter/Android では Undo/Redo・セーブ/ロード・トランザクションに応用できる
- Command = 操作の履歴 / Memento = 状態の履歴 と整理すると理解しやすい