메멘토 패턴

메멘토 패턴(memento pattern)은 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 소프트웨어 디자인 패턴이다. (롤백을 통한 실행 취소)
메멘토 패턴은 3개의 객체로 구현된다: 오리지네이터(originator), 케어테이커(caretaker), 메멘토(memento). 오리지네이터는 내부 상태를 보유하고 있는 일부 객체이다. 케어테이커는 오리지네이터에 대해 무언가를 하지만 변경에 대한 실행 취소를 하기를 원한다.  케어테이커는 먼저 오리지네이터에게 메멘토 객체를 요청한다. 그 뒤 예정된 일련의 명령을 수행한다. 명령 이전의 상태로 되돌리기 위해 메멘토 객체를 오리지네이터에 반환한다. 메멘토 객체 자신은 불투명 자료형(케어테이커는 변경할 수 없거나 변경해서는 안 되는)이다.
메멘토 패턴의 전형적인 예로 유사난수의 시드(seed), 유한 상태 기계의 상태(state)를 포함한다.

UML 클래스 및 시퀀스 다이어그램

위 UML 클래스 다이어그램에서, Caretaker 클래스는 오리지네이터의 내부 상태를 저장(createMemento())하고 복구(restore(memento))하기 위해 Originator 클래스를 참조한다.
Originator 클래스는 다음을 구현한다.
(1) 오리지네이터의 현재 내부 상태를 저장하는 Memento 객체를 생성하고 돌려주는 createMemento()
(2) Memento 객체로 전달된 상태를 복구하는 restore(memento)
UML 시퀀스 다이어그램은 런타임 인터렉션을 보여준다.
(1) 오리지네이터의 내부 상태를 저장: Caretaker 객체는, Memento 객체를 생성하고 현재 내부 상태를 저장하고(setState()), Caretaker로 Memento를 돌려주는 Originator 객체의 createMemento()를 호출한다.
(2) 오리지네이터의 내부 상태를 복구: Caretaker는 Originator 객체의 restore(memento)를 호출하고 복구할 상태를 저장하고있는 Memento 객체를 가져온다(getState()).

C# 예시

메멘토 패턴은 캡슐화를 훼손하지 않고 객체의 내부 상태를 캡쳐할 수 있게 해주므로 이후에 필요한 경우 변경사항을 되돌리거나 취소할 수 있다. 다음 코드에서는 객체에서 발생한 변경사항을 취소하기위해 메멘토 객체가 실제로 사용되는 것을 볼 수 있다.
 1 public class OriginalObject
 2 {
 3     public string String1 { get; set; }
 4     public string String2 { get; set; }
 5 
 6     public OriginalObject(string str1, string str2)
 7     {
 8         this.String1 = str1;
 9         this.String2 = str2;
10     }
11 
12     public void SetMemento(Memento memento)
13     {
14         this.String1 = memento.string1;
15         this.String2 = memento.string2;
16     }
17 
18     public Memento CreateMemento()
19     {
20         return new Memento(this.String1, this.String2);
21     }
22 }
23 
24 //Memento object
25 public class Memento
26 {
27     public readonly string string1;
28     public readonly string string2;
29 
30     public Memento(string str1, string str2)
31     {
32         this.string1 = str1;
33         this.string2 = str2;
34     }
35 }
36 
37 //CareTaker Object
38 public class CareTaker
39 {
40     public Memento Memento { get; set; }
41 }
42 
43 //Client
44 class Program
45 {
46     static void Main(string[] args)
47     {
48         // Create Originator object which container first state of "First" and "One". 
49         // The Memento will remember these value.
50         OriginalObject original = new OriginalObject("First", "One");
51 
52         // Create first State and store to caretaker
53         Memento firstMemento = original.CreateMemento();
54         CareTaker caretaker = new CareTaker();
55         caretaker.Memento = firstMemento;
56 
57         // Change into second state; "Second" and "Two".
58         original.String1 = "Second";
59         original.String2 = "Two";
60 
61         // Retrieve back first State
62         original.SetMemento(caretaker.Memento);
63         
64     }
65 }

Python 예시

"""Memento pattern example."""class Memento(object):
    def __init__(self, state):
        self._state = state

    def get_saved_state(self):
        return self._state

class Originator(object):
    _state = ""

    def set(self, state):
        print("Originator: Setting state to", state)
        self._state = state

    def save_to_memento(self):
        print("Originator: Saving to Memento.")
        return Memento(self._state)

    def restore_from_memento(self, memento):
        self._state = memento.get_saved_state()
        print("Originator: State after restoring from Memento:", self._state)


saved_states = []
originator = Originator()
originator.set("State1")
originator.set("State2")
saved_states.append(originator.save_to_memento())

originator.set("State3")
saved_states.append(originator.save_to_memento())

originator.set("State4")

originator.restore_from_memento(saved_states[0])