Memento

2 minute read

Memento pattern - 행위 패턴


사용 목적

메멘토 패턴은 객체의 상태 정보를 저장하고 사용자의 필요에 의하여 원하는 시점의 데이터를 복원 할 수 있는 패턴을 의미합니다. 즉,

  • 어떤 객체의 상태에 대한 스냅샷(몇 개의 일부)을 저장한 후 나중에 이 상태로 복구해야 할 때.

  • 상태를 얻는 데 필요한 직접적인 인터페이스를 두면 그 객체의 구현 세부사항이 드러날 수밖에 없고, 이것으로 객체의 캡슐화가 깨질 때.


UML Diagram

alt_text

  • Memento(SolverState) : 원조본 객체의 내부 상태를 저장하는 클래스. 이상적인 메멘토 생성은 원조본 객체만이 메멘토의 내부 상태에 접근할 수 있어야 합니다.

  • Originator(ConstraintSolver) : 원조본 객체. 메멘토를 생성하여 현재 상태를 저장하고, 메멘토를 사용하여 내부 상태를 복원합니다. 또한, 메멘토 클래스의 두 가지 인터페이스 중 광범위 인터페이스를 담당합니다. 즉, 자신의 상태를 이전 상태로 복원하기 위해 필요한 모든 자료에 접근하게 해주는 클래스.

  • Caretaker(실행 취소 메커니즘) : 메멘토의 보관을 책임지는 보관자. 메멘토의 내용을 검사하거나 그 내용을 건드리지는 않습니다. 또한, 메멘토 클래스의 두 가지 인터페이스 중 제한범위 인터페이스에 해당합니다.


예제

alt_text

  • User : 메멘토 패턴이 적용 된 Information 객체를 실제로 사용하는 사용자.

  • Information : 상태를 저장하고 복원 할 데이터를 가지고 있는 클래스. -> Originator

  • Memento : 특정 시점의 Information의 상태정보를 저장하는 클래스. -> Memento

  • CareTaker : 상태 정보가 저장되어 있는 Memento들을 관리하는 클래스입니다. 내부에 Stack 자료형 변수를 가짐으로써 Memento 객체를 저장하고 복원을 합니다. (스택이 아닌 리스트나 맵 계열도 사용 가능함. 순차적인 기억 정보를 불러오는 스택과 달리 인덱스, 혹은 키/밸류를 이용한 상태 정보 저장과 불러오기가 가능함.)

// Originator 를 통해서만 상태를 저장하고, 복원하는것이 가능하다.
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 RestoreMemento(Memento memento) {  //Memento를 복원합니다 (상태복원)
		this.Data1 = memento.getData1();
		this.Data2 = memento.getData2();
	}
	public void set_Data1(String Data1){
		this.Data1 = Data1;
	}
	public void set_Data2(int Data2){
		this.Data2 = Data2;
	}
	public String get_Data1() {
		return this.Data1;
	}
	public int get_Data2() {
		return this.Data2;
	}
}
// 생성자를 통한 상태 정보 저장과, 불러오기를 담당함.
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;
	}
}
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();
	}
}
public class User {
	public static void main(String[] args) {
		Information info;
		Caretaker caretaker;
		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.RestoreMemento(caretaker.pop());
		//상태 정보를 복원 한 후에 Information의 상태 정보를 출력합니다.
		System.out.println("복구된 Data1 : " + info.get_Data1());
		System.out.println("복구된 Data2 : " + info.get_Data2());
	}
}

참고 자료

  • https://keichee.tistory.com/category/Programming/GoF%20Design%20Pattern
  • https://lktprogrammer.tistory.com/65
  • https://kunoo.tistory.com/entry/%ED%96%89%EC%9C%84-%ED%8C%A8%ED%84%B4-Memento-pattern-%EB%A9%94%EB%A9%98%ED%86%A0-%ED%8C%A8%ED%84%B4
  • GOF Design Pattern

Updated: