<디자인패턴입문> 15. Memento 패턴
by BFine
www.yes24.com/Product/Goods/2918928
가. 무엇인가
a. 추억...
- Memento는 기억이라는 의미를 가지고 있다. Memento(메멘토) 패턴도 이 기억이라는 키워드에 대한 패턴이다.
- 워드나 한글 같은 텍스트 에디터를 사용할때 실수로 작성 중인 글을 지워도 실행취소(Ctrl+Z)로 복원할 수 있다.
- 객체지향에서 undo를 만들려면 인스턴스가 가지고 있던 정보를 저장할 필요가 있다.
=> 필요할때 이 저장된 기억으로 되돌리는 것이 필요하다.
- 복원하기 위해서는 인스턴스 내부 정보를 자유롭게 액세스 할 수 있어야한다.
- 하지만 원치않은 액세스를 허용하면 내부 구조에 의존한 코드가 여기저기 흩어져 수정을 어렵게 만들 수 있다.
=> 이를 캡슐화의 파괴라고 한다.
b. 상태를 기억
- Memento(메멘토) 패턴은 인스턴스의 상태를 나타내는 역할를 도입해 저장과 복원을 실행하는 패턴이다.
나. 만들어본 예제
a. Originator(작성자)의 역할
- Originator의 역할은 자신의 현재 상태를 저장하고 싶을때 Memento 역할을 만들어서 저장한다.
- 그리고 복원할경우 이전기억인 Memento의 정보를 가져와서 해당시점의 상태로 돌리는 역할을 한다.
- 또한 Memento를 설정하는 부분은 다른패키지에서 접근하지 못하도록 캡슐화한다.
b. Memento(기억)의 역할
- Memento 역할은 Originator 역할의 시점 상태를 가지고 있으며 다른 클래스에 정보를 공개하지 않는다.
- Originator 안에 private class 형태로 추가가 되어 외부에서는 존재를 모르도록 캡슐화한다.
package memento.game;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class GameInventoryOriginator {
private List<String> inventory;
private Stack<Memento> mementoStack;
public GameInventoryOriginator() {
this.inventory = new ArrayList<>();
this.mementoStack = new Stack<>();
}
public void obtainItem(String item){
inventory.add(item);
}
public void printInventory(){
System.out.println(String.join(", ",inventory));
}
void saveGame(){
mementoStack.push(new Memento(new ArrayList<>(inventory)));
}
void loadGame(){
Memento memento = mementoStack.pop();
inventory = memento.getInventory();
}
private class Memento {
private final List<String> inventory;
Memento(List<String> inventory) {
this.inventory = inventory;
}
List<String> getInventory() {
return inventory;
}
}
}
c. Caretaker(관리인)의 역할
- Originator의 현재 상태를 저장하고 싶을때 Originator에게 전달하여 Originator가 정보를 저장하도록 한다.
- 또한 이전데이터로 복원하고 싶은 경우에도 전달하여 복원하도록 한다.
package memento.game;
public class Caretaker {
public void save(GameInventoryOriginator gameInventory){
gameInventory.saveGame();
}
public void load(GameInventoryOriginator gameInventory){
gameInventory.loadGame();
}
}
d. Main
- Originator의 데이터를 복원하고 싶은 경우 패키지가 다르기 때문에 Caretaker를 통해서만 실행가능하다.
package memento;
import memento.game.Caretaker;
import memento.game.GameInventoryOriginator;
public class Main {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
GameInventoryOriginator game = new GameInventoryOriginator();
game.obtainItem("포션");
game.obtainItem("화살");
game.obtainItem("5성지팡이");
game.printInventory();
caretaker.save(game);
game.obtainItem("양손검");
game.obtainItem("불길한상자");
game.printInventory();
caretaker.load(game);
game.printInventory();
}
}
/**
"C:\Program Files\Java\jdk1.8.0_251\bin\java.exe"
포션, 화살, 5성지팡이
포션, 화살, 5성지팡이, 양손검, 불길한상자
포션, 화살, 5성지팡이
*/
다. 정리
a. Caretaker 역할과 Originator 역할을 분리하는 이유
- Caretaker는 어느 시점에 스냅샷을 찍을지, 언제 복원할지를 결정하는 역할을 한다.
- Originator는 기억(Memento)를 생성과 자신의 상태 복원을 하는 역할을 한다.
- 이렇게 역할분담을 수행하고 있기 때문에 만약 '복원할때 로그를 DB에 남기고 싶은 경우'
Originator 역할을 변경할 필요가 전혀없다.
Memento 패턴은 어떤 객체의 상태를 기록하여 원하는 시점에 복원할 수 있도록 하는 패턴이다.
'개발서적 > 디자인패턴입문' 카테고리의 다른 글
<디자인패턴입문> 17. Flyweight 패턴 (0) | 2021.05.10 |
---|---|
<디자인패턴입문> 16. State 패턴 (0) | 2021.05.09 |
<디자인패턴입문> 14. Observer 패턴 (0) | 2021.05.07 |
<디자인패턴입문> 13. Mediator 패턴 (0) | 2021.05.06 |
<디자인패턴입문> 12. Facade 패턴 (0) | 2021.05.05 |
블로그의 정보
57개월 BackEnd
BFine