Memento Pattern
2021. 12. 11. 22:21ㆍComputer Sciences/Design Patterns
개요
메멘토 패턴(Memento Pattern)은 객체를 이전의 상태로 복구시켜야 하는 경우에 사용되는 패턴이다. 복원, 작업 취소 등의 작업이 필요할 때 사용된다.
시나리오
한 주사위 게임이 있다. 이 게임은 주사위가 1이 나오면 100원을 얻고 2가 나오면 현재 보유한 돈이 절반이 된다. 특별한 숫자인 6이 나오면 과일을 받는다. 돈이 전부 떨어지면 게임이 종료된다.
여기서 우리는 부정행위(?)를 하려고 한다. 현재 돈이 이전보다 많아지면 현재 돈을 저장해놓는다. 그러다가 나중에 돈이 너무 적어지면 저장해놓은 돈으로 복구시킨다.
Class Diagram
코드
import java.util.ArrayList;
import java.util.List;
public class Memento {
private int money;
private ArrayList<String> fruits;
public Memento(int money) {
this.money = money;
this.fruits = new ArrayList<>();
}
public int getMoney() {
return money;
}
void addFruit(String fruit) {
fruits.add(fruit);
}
// 컬렉션을 object로 변환한 후 다시 형변환하면 항상 unchecked 경고가 발생한다.
@SuppressWarnings("unchecked")
List<String> getFruits() {
return (List<String>) fruits.clone();
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class Gamer {
private int money;
private List<String> fruits = new ArrayList<>();
private Random random = new Random();
private static String[] fruitsname = {
"사과", "포도", "바나나", "귤"
};
public Gamer(int money) {
this.money = money;
}
public int getMoney() {
return money;
}
public void bet() {
int dice = random.nextInt(6) + 1;
if (dice == 1) {
money += 100;
System.out.println("돈이 증가했습니다.");
} else if (dice == 2) {
money /= 2;
System.out.println("돈이 절반이 되었습니다.");
} else if (dice == 6) {
String f = getFruit();
System.out.println("과일(" + f + ")을 받았습니다.");
fruits.add(f);
} else {
System.out.println("변한 값이 없습니다.");
}
}
public Memento createMemento() {
Memento m = new Memento(money);
Iterator<String> iter = fruits.iterator();
// 맛있는 과일만 저장한다.
while (iter.hasNext()) {
String f = (String) iter.next();
if (f.startsWith("맛있는 ")) {
m.addFruit(f);
}
}
return m;
}
public void restoreMemento(Memento memento) {
this.money = memento.getMoney();
this.fruits = memento.getFruits();
}
public String getFruit() {
String prefix = "";
if (random.nextBoolean()) {
prefix = "맛있는 ";
}
return prefix + fruitsname[random.nextInt(fruitsname.length)];
}
@Override
public String toString() {
return "[money = " + money + ", fruits = " + fruits + "]";
}
}
public class Main {
public static void main(String[] args) {
Gamer gamer = new Gamer(100);
Memento memento = gamer.createMemento();
for (int i = 0; i < 100; i++) {
System.out.println("====" + i);
System.out.println("현재 상태:" + gamer);
gamer.bet();
System.out.println("돈은 " + gamer.getMoney() + " 원이 되었습니다.");
if (gamer.getMoney() > memento.getMoney()) {
System.out.println("(많이 증가했으므로 현재 상태를 저장하자)");
memento = gamer.createMemento();
} else if (gamer.getMoney() < memento.getMoney() / 2) {
System.out.println("(많이 감소했으므로 이전 상태로 복원하자)");
gamer.restoreMemento(memento);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println();
}
}
}
장단점
장점
- 저장된 상태를 핵심 객체와 다른 별도의 객체에 보관하기 때문에 안전하다.
- 핵심 객체의 데이터를 계속해서 캡슐화된 상태로 유지할 수 있다.
- 복구 기능을 구현하기 쉽다.
단점
- 상태를 저장하고 복구하는 데 시간이 오래 걸릴 수 있다.
- 자바 시스템에서는 시스템의 상태를 저장할 때 직렬화를 사용하는 것이 좋다.
'Computer Sciences > Design Patterns' 카테고리의 다른 글
Interpreter Pattern (0) | 2021.12.12 |
---|---|
Flyweight Pattern (0) | 2021.12.11 |
Visitor Pattern (0) | 2021.12.11 |
Prototype Pattern (0) | 2021.12.11 |
14. Chain of Responsibility Pattern (0) | 2021.11.14 |