객체의 내부 사항을 공개하지 않으면서 이전 상태를 저장하고 복원할 수 있게 해주는 패턴
1. level과 health를 가지고 있는 Game 클래스가 있다.
class Game {
public String level;
public int health;
public Game(String level, int health) {
this.level = level;
this.health = health;
}
public void play(String level, int health) {
this.level = level;
this.health = health;
}
public String getLevel() {
return level;
}
public int getHealth() {
return health;
}
}
Game은 현재 상태를 저장하고 각 변수의 getter가 있다.
2. Game의 상태를 복원하는 undo를 구현하기 위한 Client는 다음과 같다.
public class Client {
public static void main(String[] args) {
Game game = new Game("Level 1", 100);
String savedLevel = game.getLevel();
int savedHealth = game.getHealth();
game.play("Level 2", 80);
game.play(savedLevel, savedHealth);
}
}
Game의 상태를 복원하기 위해 Client는 Game의 내부 상태를 직접 확인해 저장한다. 그 후 복원할 시점에 해당한 상태를 set함으로 예전 상태를 복원한다.
상태만 저장하는 객체와 이 객체를 생성, 조회가 가능한 다른 객체를 통해 저장 및 복원 기능을 구현하자
현재 상태
를 가진다.1. Game
class Game {
private String level;
private int health;
public Game(String level, int health) {
this.level = level;
this.health = health;
}
public void play(String level, int health) {
this.level = level;
this.health = health;
}
public GameState save() {
return new GameState(level, health);
}
public void restore(GameState state) {
level = state.getLevel();
health = state.getHealth();
}
}
2. GameState
class GameState {
private final String level;
private final int health;
public GameState(String level, int health) {
this.level = level;
this.health = health;
}
public String getLevel() {
return level;
}
public int getHealth() {
return health;
}
}
3. Client
public class Main {
public static void main(String[] args) {
Game game = new Game("Level 1", 100);
GameState savedState = game.save();
game.play("Level 2", 80);
game.restore(savedState);
}
}
문제 상황에서 savedLevel
과 savedHealth
와 같은 내부 상태가 GameState
클래스로 나타낼 수 있고 상태 저장 및 복원은 Game
에게 GameState
를 전달함으로 동작한다.
Mement의 생성과 조작은 Originator만 할 수 있다고 설명했지만 위 코드는 GameState
의 생성과 내부 데이터 조회가 가능하다.
public 생성자와 public getter이기 때문!
이를 구현하기 위해서 JAVA에는 nested class가, C++에는 friend class를 사용하면 된다.
public class Game {
private String level;
private int health;
public void play(String level, int health) {
this.level = level;
this.health = health;
}
public GameState save() {
return new GameState(level, health);
}
public void restore(GameState state) {
level = state.level;
health = state.health;
}
public class GameState {
private final String level;
private final int health;
private GameState(String level, int health) {
this.level = level;
this.health = health;
}
}
}
class Game {
private:
string level;
int health;
public:
void play(string level, int health);
GameState* save();
void restore(GameState* state);
};
class GameState {
friend class Game;
private:
GameState(string level, int health) : level(level), health(health){}
string level;
int health;
};