'''메멘토 패턴'''(memento pattern)은 객체를 이전 상태로 되돌릴 있는 기능을 제공하는 소프트웨어 디자인 패턴이다. (롤백을 통한 실행 취소) 메멘토 패턴은 3개의 객체로 구현된다: 메멘토(memento). 오리지네이터는 내부 상태를 보유하고 있는 일부 객체이다. 케어테이커는 오리지네이터에 대해 무언가를 하지만 변경에 대한 실행 취소를 하기를 원한다. 케어테이커는 먼저 오리지네이터에게 메멘토 객체를 요청한다. 예정된 일련의 명령을 수행한다. 명령 이전의 상태로 되돌리기 위해 메멘토 객체를 오리지네이터에 반환한다. 메멘토 객체 자신은 불투명 자료형(케어테이커는 변경할 없거나 변경해서는 되는)이다. 메멘토 패턴의 전형적인 예로 유사난수의 시드(seed), 유한 상태 기계의 상태(state)를 포함한다. == 개요 == 메멘토 디자인 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하기 위해 반복되는 디자인 문제를 해결하는 방법, 객체는 구현, 변경, 테스트, 재사용이 쉬워야 한다는 것을 기술하는, 알려진 23가지 GoF 디자인 패턴들 하나이다. 메멘토 패턴은 초기 HP 제품을 위해 Noah Thompson과 Dr.Drew Clinkenbeard에 의해 제작되었다. 메멘토 디자인 패턴이 해결할 있는 문제는 무엇인가? 객체의 내부 상태가 외부적으로 저장되어야 이후에 객체가 상태를 복구할 있다. 객체의 캡슐화가 훼손되지 않아야 한다. 문제는 디자인된 객체는 캡슐화되어 있기 때문에 표현(데이터 구조)이 내부에 숨겨져 있어 객체의 외부에서 접근할 없다는 것이다. 메멘토 디자인 패턴이 설명하는 해결책은 무엇인가? 객체(오리지네이터) 자체가 다음 책임을 갖도록 한다. (메멘토) 객체에 내부 상태를 저장 (메멘토) 객체로부터 이전 상태를 복구 메멘토를 생성한 오리지네이터만이 접근이 허용된다. 클라이언트(케어테이커)는 오리지네이터로부터 메멘토를 요청하고(오리지네이터의 내부 상태를 저장하기 위해) 오리지네이터에게 메멘토를 다시 돌려줄 있다(이전 상태로 복구하기 위해). 이는 캡슐화를 훼손하지 않고 오리지네이터의 내부 상태를 저장하고 복구할 있게해준다. 아래 UML 클래스 시퀀스 다이어그램을 함께 보자. == 구조 == === UML 클래스 시퀀스 다이어그램 === 메멘토 디자인 패턴을 위한 샘플 UML 클래스와 시퀀스 다이어그램.위 UML 클래스 다이어그램에서, Caretaker 클래스는 오리지네이터의 내부 상태를 위해 Originator 클래스를 참조한다. Originator 클래스는 다음을 구현한다. (1) 오리지네이터의 현재 내부 상태를 저장하는 Memento 객체를 생성하고 돌려주는 createMemento() (2) Memento 객체로 전달된 상태를 복구하는 UML 시퀀스 다이어그램은 런타임 인터렉션을 보여준다. (1) 오리지네이터의 내부 상태를 저장: Caretaker 객체는, Memento 객체를 생성하고 현재 내부 상태를 Caretaker로 Memento를 돌려주는 Originator 객체의 호출한다. (2) 오리지네이터의 내부 상태를 복구: Caretaker는 Originator 객체의 호출하고 복구할 상태를 저장하고있는 Memento 객체를 == 자바 예시 == 다음 Java 프로그램은 메멘토 패턴의 "undo" 사용을 보여준다. '''import''' '''import''' '''class''' '''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) state; Setting state to state); '''public''' Memento saveToMemento() Saving to Memento."); '''return''' '''new''' '''public''' void memento) 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 savedStates '''new''' ArrayList(); Originator originator '''new''' Originator(); ''// We can request multiple mementos, and choose which one to roll back to.'' 출력은 다음과 같다. 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 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 copy of the state must be done. 예시에서는 Java에서 불변한 객체인 String을 상태로써 사용한다. 실제 시나리오에서는 상태가 거의 항상 객체일 것이며, 상태의 복사가 반드시 이루어져야 한다. 내부 클래스를 선언한것에 대해 구현이 취약점을 보인다고 말할 있을 것이다. 메멘토 전략은 오리지네이터가 하나 이상일 적용한다면 나을 것이다. 메멘토를 달성하는 다른 가지 주요 방법은 다음과 같다. 직렬화. 동일한 패키지에 선언된 클래스. 객체에 저장/복구 작업을 있는 프록시를 통해 접근할 수도 있는 객체. == C# 예시 == 메멘토 패턴은 캡슐화를 훼손하지 않고 객체의 내부 상태를 캡쳐할 있게 해주므로 이후에 필요한 경우 변경사항을 되돌리거나 취소할 있다. 다음 코드에서는 객체에서 발생한 변경사항을 취소하기 위해 ''메멘토 객체''가 실제로 사용되는 것을 있다. '''public''' '''class''' '''public''' string String1 '''get'''; '''set'''; '''public''' string String2 '''get'''; '''set'''; '''public''' str1, string str2) str1; str2; 10 11 12 '''public''' '''void''' memento) 13 14 15 16 17 18 '''public''' Memento CreateMemento() 19 20 '''return''' '''new''' 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 str1; 33 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''' "One"); 51 52 ''// Create first State and store to caretaker'' 53 Memento firstMemento 54 CareTaker caretaker '''new''' CareTaker(); 55 firstMemento; 56 57 ''// Change into second state; "Second" and "Two".'' 58 "Second"; 59 "Two"; 60 61 ''// Retrieve back first State'' 62 63 64 65 == Python 예시 == ''"""'' ''Memento pattern example.'' ''"""'' '''class''' '''def''' __init__(self, state): self._state state '''def''' '''return''' self._state '''class''' _state "" '''def''' set(self, state): Setting state to", state) self._state state '''def''' Saving to Memento.") '''return''' '''def''' memento): self._state State after restoring from Memento:", self._state) saved_states originator Originator() == 각주 == == 외부 링크 == Description of Memento Pattern in Ada Memento UML Class Diagram with C# and .NET code samples SourceMaking Tutorial Memento Design Pattern using Java 분류:소프트웨어 디자인 패턴