Memento Pattern은 인스턴스의 상태를 되돌리고 싶을 때 그 전의 인스턴스를 저장하고 있어야한다. 하지만 과거의 상태로 되돌리려면 클래스에 마음대로 접근할 수 있어야합니다. 그런데 잘못된 접근을 하게 된다면 의존 되어있는 코드가 여기저기 흩어지게 됩니다. 이러한 상태를 캡슐화의 파괴라고합니다.
캡슐화의 파괴를 일으키지 않고 상태(이전의 인스턴스)를 저장하게 해주는 패턴을 Memento Pattern이라고 합니다.
- 상태를 저장하여 필요할때 마다 바꿔주고 다시 저장한다.
예시 프로그램으로 텍스터나 ide 등에서 ctrl + z 나 command + z를 통해 과거의 상태로 돌아갈 수 있게 해줍니다. 이러한 상황에서도 보통 Memento Pattern을 사용하게 됩니다.
각종 역활
Originator (작성자)
게임 진행자의 역활을 수행하며 Memento를 만들거나 되돌리는 처리를 실행합니다.
Memento
사용자의 정보를 저장합니다. 하지만 정보를 공개하진 않습니다.
Caretaker(관리인)
Caretaker 역활은 현재의 Originator의 정보를 저장하거나 restore할 때 사용한다. Caretaker는 Memento가 어떤 구조로 이루어져있는지 알 수 없다. 얕은 연결로 이루어 져있다.
파일 구조
UML
Memento.java (Memento)
변수나 함수에 모두 public, private 등 접근 제안문이 안붙어있습니다. 이는 game 이외의 패키지에서는 내부를 변경할 수 없다는 뜻입니다.
package game; import java.util.*; public class Memento{ int money; ArrayList fruits; public int getMoney(){ return money; } Memento(int money){ this.money = money; this.fruits = new ArrayList(); } void addFruit(String fruit){ fruits.add(fruit); } List getFruits(){ return (List)fruits.clone(); } }
Gamer.java(Originator)
bet 함수는 gamer가 게임을 실행하는 겁니다.
createMemento() 는 현재상황을 save하고 있는 객체를 만드는 것입니다.
restoreMemento는 save한 Memento로 되돌려 놓는 함수입니다.
package game; import java.util.*; public class Gamer { private int money; private List 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 it = fruits.iterator(); while(it.hasNext()){ String f = (String)it.next(); if(f.startsWith("맛있는")) m.addFruit(f); } return m; } public void restoreMemento(Memento memento){ this.money = memento.money; this.fruits = memento.getFruits(); } public String toString(){ return "[money = " + money + ", fruits = "+fruits + "]"; }