Memento Pattern
Memento Pattern === "undo"
1. 메멘토 패턴(memento Pattern)이란?.
위키백과에 나와있는 메멘토 패턴의 정의는
‘객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 소프트웨어 디자인 패턴’이다.
쉽게 말해, 메멘토 패턴
은 ‘undo’ 역할을 수행한다.
여기서 ‘undo’란 실행취소
혹은 수행한 기능을 되돌리는 것
을 의미한다.
2. 메멘토 패턴의 구성과 역할
1) 구성
메멘토 패턴은 3개의 객체로 구현된다.
- 오리지네이터(originator)
- 메멘토(memento)
- 케어테이커(caretaker)
2) 역할
각 객체의 역할들은 다음과 같다.
- 오리지네이터(originator) : Memento 객체를 생성해서, Originator의 snapshot(그 때 기억)을 저장한다.
- 메멘토(memento) : Originator의 state를 저장한다. Memento의 state는 외부에 노출시키지 않으며(primary), Originator에 의해서만 읽고 쓸 수 있다. 즉, Memento는 Originator의 inner class로 구현될 것이다.
- 케어테이커(caretaker) : Memento를 저장할 책임이 있다.
3) Cycle
- UML
- 수행 과정
[상황]
caretaker는 originator에 대해 어떠한 실행을 한 후 변경에 대한 실행 취소를 하기를 원한다.
[수행]
① main에서 originator의 상태를 변경한다.
② caretaker는 originator에게 memento 특정 상태를 저장(saveToMemento)한다.
③ 사용자는 1,2번 과정을 반복하다가 원하는 savepoint로 되돌리기를 원한다.
④ memento 객체를 originator에게 반환(restoreFromMemento)하여 반환한다.
3. code
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(0));
}
}
▶︎ 출력
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: State2
4. 문제
- 위 코드는 하나의 클래스로 구현한 memento 패턴이다.
- 위 코드를 참조하여 아래 네 개의 클래스로 구성된 코드를 구현해보아라.
- String형 데이터 하나와 Int형 데이터 하나에 대한 정보로 가지는 Information 객체를 구현.
● User : 메멘토 패턴이 적용 된 Information 객체를 실제로 사용하는 사용자.
● Information : 상태를 저장하고 복원 할 데이터를 가지고 있는 클래스.
● Memento : 특정 시점의 Information의 상태정보를 저장하는 클래스.
● CareTaker : 상태 정보가 저장되어 있는 Memento들을 관리하는 클래스. 내부에 Stack 자료형 변수를 가짐으로써 Memento 객체를 저장하고 복원함.
1) 힌트
2) 해답
Information.java
public class Information {
private String Data1; //Information이 가지고 있는 데이터1
private int Data2; //Information이 가지고 있는 데이터2
public Information(String Data1, int Data2) //생성자입니다.
{
this.Data1 = Data1;
this.Data2 = Data2;
}
public Memento CreateMemento() //Memento를 생성합니다 (상태저장)
{
return new Memento(this.Data1,this.Data2);
}
public void RestorMemento(Memento memento) //Memento를 복원합니다 (상태복원)
{
this.Data1 = memento.getData1();
this.Data2 = memento.getData2();
}
public void set_Data1(String Data1) //데이터1의 값을 지정
{
this.Data1 = Data1;
}
public void set_Data2(int Data2) //데이터2의 값을 지정
{
this.Data2 = Data2;
}
public String get_Data1() //데이터 1의 값 반환
{
return this.Data1;
}
public int get_Data2() //데이터 2의 값 반환
{
return this.Data2;
}
}
Memento.java
public class Memento {
//Information의 상태정보를 가지고 있음
private String Data1;
private int Data2;
public Memento(String Data1,int Data2)
{
this.Data1 = Data1;
this.Data2 = Data2;
}
public String getData1()
{
return this.Data1;
}
public int getData2()
{
return this.Data2;
}
}
CareTaker.java
import java.util.Stack;
public class CareTaker {
Stack<Memento> mementos = new Stack<>(); //Memento 관리를 위한 Stack
public void push(Memento memento) //특정 시점에 생성된 Memento를 Push
{
mementos.push(memento);
}
public Memento pop() //복원을 위한 Memento 객체 반환
{
return mementos.pop();
}
}
User.java
public class User {
Information info;
CareTaker caretaker;
public void exe()
{
info = new Information("Data1",10); //Information 객체 생성
caretaker = new CareTaker(); //CareTaker 객체 생성
//현재 Information의 상태 정보를 가지는 Memento를 생성하여 CareTaker에 추가합니다.
caretaker.push(info.CreateMemento());
//Information 정보를 수정합니다.
info.set_Data1("Data2");
info.set_Data2(20);
//현재 Information의 상태정보를 출력합니다.
System.out.println("현재 Data1 : " + info.get_Data1());
System.out.println("현재 Data2 : " + info.get_Data2());
//가장 최근에 생성 된 Memento를 가지고와서 상태 정보를 복원합니다.
info.RestorMemento(caretaker.pop());
//상태 정보를 복원 한 후에 Information의 상태 정보를 출력합니다.
System.out.println("복구된 Data1 : " + info.get_Data1());
System.out.println("복구된 Data2 : " + info.get_Data2());
}
}
▶︎ 출력
현재 Data1 : Data2
현재 Data2 : 20
복구된 Data1 : Data1
복구된 Data2 : 10
댓글남기기