메멘토 패턴
- 캡슐화를 유지하면서 객체의 내부 상태를 외부에서 저장하고 복원할 수 있게 지원하는 디자인 패턴
- 객체 상태를 외부에 저장했다가 해당 상태로 다시 복구할 수 있음
- 메멘토 패턴의 주요 목적은 원본 객체의 상태를 캡슐화하여 외부에서 직접 접근하지 않고도 저장하고 복원할 수 있게 하는 것

주요 구성 요소
1. Originator
- 현재 상태를 저장하고 복원할 객체
2. Memento
- 원본 객체의 상태를 저장하는 객체
3. Caretaker
- 메멘토 객체를 관리하며 필요시 원본 객체의 상태를 복원
메멘토 패턴 구현 예시
- Originator 객체의 상태를 여러 번 변경하고, 상태를 메멘토 객체로 저장한 후, 나중에 이를 복원하는 과정
1. Originator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Originator { | |
private String state; | |
public void setState(String state) { | |
this.state = state; | |
} | |
public String getState() { | |
return state; | |
} | |
public Memento saveStateToMemento() { | |
return new Memento(state); | |
} | |
public void getStateFromMemento(Memento memento) { | |
state = memento.getState(); | |
} | |
} |
2. Memento
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Memento { | |
private final String state; | |
public Memento(String state) { | |
this.state = state; | |
} | |
public String getState() { | |
return state; | |
} | |
} |
3. Caretaker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Caretaker { | |
private List<Memento> mementoList = new ArrayList<>(); | |
public void add(Memento state) { | |
mementoList.add(state); | |
} | |
public Memento get(int index) { | |
return mementoList.get(index); | |
} | |
} |
4. 클라이언트 코드
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Client { | |
public static void main(String[] args) { | |
Originator originator = new Originator(); | |
Caretaker caretaker = new Caretaker(); | |
originator.setState("상태 #1"); | |
originator.setState("상태 #2"); | |
caretaker.add(originator.saveStateToMemento()); | |
originator.setState("상태 #3"); | |
caretaker.add(originator.saveStateToMemento()); | |
originator.setState("상태 #4"); | |
System.out.println("현재 상태: " + originator.getState()); | |
originator.getStateFromMemento(caretaker.get(0)); | |
System.out.println("첫 번째 상태 복원: " + originator.getState()); | |
originator.getStateFromMemento(caretaker.get(1)); | |
System.out.println("두 번째 상태 복원: " + originator.getState()); | |
} | |
} |

메멘토 패턴 장단점
장점
- 메멘토 패턴을 사용하면 객체의 내부 상태를 외부에서 직접 접근하지 않고도 저장하고 복원할 수 있으며 이는 객체의 캡슐화를 유지하면서도 객체의 상태를 관리할 수 있게 지원
- 객체 상태 저장 및 복원하는 역할을 Caretaker에게 위임할 수 있음
- 객체 상태가 바뀌어도 클라이언트 코드는 변경되지 않음 (SOLID의 OCP 원칙)
단점
- 많은 정보를 저장하는 Mementor를 자주 생성할수록 메모리 사용량에 많은 영향을 줄 수 있음
- 객체의 모든 상태를 메멘토에 저장해야 하는데 객체의 상태가 복잡하거나 많은 경우 구현이 복잡해질 수 있음
실무에서 쓰이는 메멘토 패턴
1. java.io.Serializable
- java.io.Serializable 인터페이스는 자바에서 객체를 직렬화할 수 있도록 해주는 인터페이스
- 직렬화는 객체의 상태를 저장하거나 전송하기 위해 객체를 바이트 스트림으로 변환하는 과정
- 메멘토 패턴과 Serializable을 결합하면, 객체의 상태를 보다 쉽게 저장하고 복원할 수 있으며 이는 메멘토 패턴의 주요 목적과 일치
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Originator implements Serializable { | |
private static final long serialVersionUID = 1L; | |
private String state; | |
public void setState(String state) { | |
this.state = state; | |
} | |
public String getState() { | |
return state; | |
} | |
public Memento saveStateToMemento() { | |
return new Memento(state); | |
} | |
public void getStateFromMemento(Memento memento) { | |
state = memento.getState(); | |
} | |
// 내부 클래스로 Memento 구현 | |
public static class Memento implements Serializable { | |
private static final long serialVersionUID = 1L; | |
private final String state; | |
public Memento(String state) { | |
this.state = state; | |
} | |
public String getState() { | |
return state; | |
} | |
} | |
} | |
class Caretaker { | |
public void saveMemento(Originator.Memento memento, String filename) throws IOException { | |
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) { | |
oos.writeObject(memento); | |
} | |
} | |
public Originator.Memento loadMemento(String filename) throws IOException, ClassNotFoundException { | |
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) { | |
return (Originator.Memento)ois.readObject(); | |
} | |
} | |
} | |
public class Client { | |
public static void main(String[] args) { | |
try { | |
Originator originator = new Originator(); | |
Caretaker caretaker = new Caretaker(); | |
originator.setState("상태 #1"); | |
System.out.println("현재 상태: " + originator.getState()); | |
Originator.Memento memento1 = originator.saveStateToMemento(); | |
caretaker.saveMemento(memento1, "memento1.ser"); | |
originator.setState("상태 #2"); | |
System.out.println("현재 상태: " + originator.getState()); | |
Originator.Memento memento2 = originator.saveStateToMemento(); | |
caretaker.saveMemento(memento2, "memento2.ser"); | |
// 상태 복원 | |
Originator.Memento restoredMemento1 = caretaker.loadMemento("memento1.ser"); | |
originator.getStateFromMemento(restoredMemento1); | |
System.out.println("첫 번째 상태 복원: " + originator.getState()); | |
Originator.Memento restoredMemento2 = caretaker.loadMemento("memento2.ser"); | |
originator.getStateFromMemento(restoredMemento2); | |
System.out.println("두 번째 상태 복원: " + originator.getState()); | |
} catch (IOException | ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |

참고
코딩으로 학습하는 GoF의 디자인 패턴 - 백기선 강사님
반응형
'Design Pattern' 카테고리의 다른 글
[디자인 패턴] 상태 패턴 (State Pattern) (0) | 2024.07.03 |
---|---|
[디자인 패턴] 옵저버 패턴 (Observer Pattern) (0) | 2024.07.02 |
[디자인 패턴] 커맨드 패턴 (Command Pattern) (0) | 2024.06.30 |
[디자인 패턴] 이터레이터 패턴 (Iterator Pattern) (0) | 2024.06.30 |
[디자인 패턴] 인터프리터 패턴 (Interpreter Pattern) (0) | 2024.06.30 |