**메멘토 패턴**(memento pattern)은 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 소프트웨어 디자인 패턴이다. (롤백을 통한 실행 취소)

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

메멘토 패턴의 전형적인 예로 유사난수의 시드(seed), 유한 상태 기계의 상태(state)를 포함한다.

개요
--

메멘토 디자인 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하기 위해 반복되는 디자인 문제를 해결하는 방법, 즉 객체는 구현, 변경, 테스트, 재사용이 쉬워야 한다는 것을 기술하는, 잘 알려진 23가지 GoF 디자인 패턴들 중 하나이다. 메멘토 패턴은 초기 HP 제품을 위해 Noah Thompson과 Dr.Drew Clinkenbeard에 의해 제작되었다.

메멘토 디자인 패턴이 해결할 수 있는 문제는 무엇인가?

* 객체의 내부 상태가 외부적으로 저장되어야 이후에 객체가 그 상태를 복구할 수 있다.
* 객체의 캡슐화가 훼손되지 않아야 한다.

문제는 잘 디자인된 객체는 캡슐화되어 있기 때문에 그 표현(데이터 구조)이 내부에 숨겨져 있어 객체의 외부에서 접근할 수 없다는 것이다.

메멘토 디자인 패턴이 설명하는 해결책은 무엇인가?

객체(오리지네이터) 자체가 다음 책임을 갖도록 한다.

* (메멘토) 객체에 그 내부 상태를 저장
* (메멘토) 객체로부터 이전 상태를 복구

메멘토를 생성한 오리지네이터만이 접근이 허용된다.

클라이언트(케어테이커)는 오리지네이터로부터 메멘토를 요청하고(오리지네이터의 내부 상태를 저장하기 위해) 오리지네이터에게 메멘토를 다시 돌려줄 수 있다(이전 상태로 복구하기 위해).

이는 캡슐화를 훼손하지 않고 오리지네이터의 내부 상태를 저장하고 복구할 수 있게해준다.

아래 UML 클래스 및 시퀀스 다이어그램을 함께 보자.

구조
--

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

메멘토 디자인 패턴을 위한 샘플 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()`).

자바 예시
-----

다음 자바 프로그램은 메멘토 패턴의 "undo" 사용을 보여준다.

```
**import** **java.util.List**;
**import** **java.util.ArrayList**;
**class** **Originator** {
    **private** String state;
    *// The class could also contain additional data that is not part of the*
    *// state saved in the memento..*
```

```
    **public** void set(String state) {
        **this**.state = state;
        System.out.println("Originator: Setting state to "+ state);
    }
```

```
    **public** Memento saveToMemento() {
        System.out.println("Originator: Saving to Memento.");
        **return** **new** Memento(**this**.state);
    }
```

```
    **public** void restoreFromMemento(Memento memento) {
        **this**.state = memento.getSavedState();
        System.out.println("Originator: State after restoring from Memento: "+ state);
    }
```

```
    **public** **static** **class** **Memento** {
        **private** **final** String state;
```

```
        **public** Memento(String stateToSave) {
            state = stateToSave;
        }
```

```
        *// accessible by outer class only*
        **private** String getSavedState() {
            **return** state;
        }
    }
}
```

```
**class** **Caretaker** {
    **public** **static** void main(String[] args) {
        List<Originator.Memento> savedStates = **new** ArrayList<Originator.Memento>();
```

```
        Originator originator = **new** Originator();
        originator.set("State1");
        originator.set("State2");
        savedStates.add(originator.saveToMemento());
        originator.set("State3");
        *// We can request multiple mementos, and choose which one to roll back to.*
        savedStates.add(originator.saveToMemento());
        originator.set("State4");
```

```
        originator.restoreFromMemento(savedStates.get(1));
    }
}
```

출력은 다음과 같다.

```
Originator: Setting state to State1
Originator: Setting state to State2
Originator: Saving to Memento.
Originator: Setting state to State3
Originator: Saving to Memento.
Originator: Setting state to State4
Originator: State after restoring from Memento: State3
```

This example uses a String as the state, which is an immutable object in Java. In real-life scenarios the state will almost always be an object, in which case a copy of the state must be done.

이 예시에서는 Java에서 불변한 객체인 String을 상태로써 사용한다. 실제 시나리오에서는 상태가 거의 항상 객체일 것이며, 상태의 복사가 반드시 이루어져야 한다.

내부 클래스를 선언한것에 대해 구현이 취약점을 보인다고 말할 수 있을 것이다. 이 메멘토 전략은 오리지네이터가 하나 이상일 때 적용한다면 더 나을 것이다.

메멘토를 달성하는 다른 세 가지 주요 방법은 다음과 같다.

1. 직렬화.
2. 동일한 패키지에 선언된 클래스.
3. 객체에 저장/복구 작업을 할 수 있는 프록시를 통해 접근할 수도 있는 객체.

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])
```