기타/북스터디
[디자인패턴] 메멘토패턴
Ratel
2023. 1. 29. 08:58
1. 메멘토패턴(memento pattern)이란?
메멘토패턴은 객체 내부의 상태를 외부에 저장을 하고 저장된 상태를 다시 복원하고자 할 때에 사용하는 패턴이다.
메멘토패턴을 사용함으로써 객체의 모든 정보를 외부로 노출시키지 않고 캡슐화를 지킬 수 있다.
Originator는 본래의 상태를 가지고 있고 상태를 저장하고 복원하고 싶어하는 객체이다.
Memento는 immutable한 객체로 일정 시점의 Originator 내부정보를 가지고 있다.
CareTaker는 Originator의 내부정보를 Memento type으로 가지고 있고 복원을 할 수 있는 객체이다.
2. 메멘토패턴을 사용하지 않은 코드
게임의 현재 스테이지와 캐릭터의 정보를 가지고 있는 클래스가 있다고 가정해보자.
public class Game {
private int stage;
private Character character;
public int getStage() {
return stage;
}
public void setStage(int stage) {
this.stage = stage;
}
public Character getCharacter() {
return character;
}
public void setCharacter(Character character) {
this.character = character;
}
}
그리고 게임이 진행 중에 이전 시점으로 돌리는 상황을 가정한 클라이언트를 코드를 봐보자.
public class Client {
public static void main(String[] args) {
Game game = new Game();
game.setStage(10);
game.setCharacter(new Character());
int stage = game.getStage();
Character character = game.getCharacter();
Game restoredGame = new Game();
restoredGame.setStage(stage);
restoredGame.setCharacter(character);
}
}
위와 같은 코드의 문제점은 아래와 같다.
1. 캡슐화가 깨지게 된다.
- 클라이언트가 게임이 구성하는 요소가 무엇인지 알게 된다.
2. 클라이언트가 Game객체에 의존하게 된다.
- Game의 멤버가 바뀜에 따라 클라이언트 코드가 바뀌어야한다.
3. 메멘토패턴을 적용해보자.
먼저, 메멘토 클래스를 만들어보자.
public final class GameSave {
private final int stage;
private final Character character;
public GameSave(int stage, Character character) {
this.stage = stage;
this.character = character;
}
public int getStage() {
return stage;
}
public Character getCharacter() {
return character;
}
}
그리고 Originator인 Game 클래스에서는 메멘토를 사용하여 저장하고 복원할 수 있는 메서드를 만들어주자.
public class Game {
private int stage;
private Character character;
public int getStage() {
return stage;
}
public void setStage(int stage) {
this.stage = stage;
}
public Character getCharacter() {
return character;
}
public void setCharacter(Character character) {
this.character = character;
}
public GameSave save() {
return new GameSave(this.stage, this.character);
}
public Game restore(GameSave gameSave) {
this.stage = gameSave.getStage();
this.character = gameSave.getCharacter();
}
}
이렇게 Originator와 Memento를 만들어주면 클라이언트 코드는 아래와 같이 변경된다.
public class Client {
public static void main(String[] args) {
Game game = new Game();
game.setStage(10);
game.setCharacter(new Character(1, "memento"));
GameSave save = game.save();
game.setStage(12);
game.setCharacter((new Character(15, "visitor")));
game.restore(save);
System.out.println(game.getStage());
System.out.println(game.getCharacter().getLevel());
System.out.println(game.getCharacter().getName());
}
}
실행을 시켜보면 아래와 같이 game의 이전 정보가 보여지는 것을 볼 수 있다.