학습목표

  1. 객체 상태를 외부에 노출하지 않고 저장/복원할 수 있는 방법 이해
  2. 실행 취소(Undo), 체크포인트, 히스토리 관리 등에 적용하는 방식 학습
  3. Originator / Memento / Caretaker 역할 분리를 이해하고 구현 능력 확보

활용방법

  • 텍스트 에디터 작성 내용 되돌리기
  • 체크포인트 저장 후 재시작
  • 사용자가 취소 -> 최근 상태 복원
  • 실패 시 이전 트랜잭션 상태로 롤백

예제

더보기

텍스트 편집 + Undo/Redo + Diff 저장 방식

  • Snapshot ( Memento )
public class Snapshot {
    private final String state;

    public Snapshot(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}
  • TextEditor ( Originator )
public class TextEditor {
    private String text = "";

    public void type(String words) {
        text += words;
    }

    public Snapshot save() {
        return new Snapshot(text);
    }

    public void restore(Snapshot snapshot) {
        if (snapshot != null) {
            this.text = snapshot.getState();
        }
    }

    public String getText() {
        return text;
    }
}
  • HistoryManager ( Caretaker )
public class HistoryManager {

    private final Stack<Snapshot> undoStack = new Stack<>();
    private final Stack<Snapshot> redoStack = new Stack<>();

    public void save(Snapshot snapshot) {
        undoStack.push(snapshot);
        redoStack.clear();
    }

    public Snapshot undo() {
        if (undoStack.isEmpty()) return null;
        Snapshot snapshot = undoStack.pop();
        redoStack.push(snapshot);
        return undoStack.isEmpty() ? null : undoStack.peek();
    }

    public Snapshot redo() {
        if (redoStack.isEmpty()) return null;
        Snapshot snapshot = redoStack.pop();
        undoStack.push(snapshot);
        return snapshot;
    }
}
  • 실행
public class Main {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        HistoryManager history = new HistoryManager();

        editor.type("Hello ");
        history.save(editor.save());

        editor.type("World!");
        history.save(editor.save());

        System.out.println(editor.getText()); // Hello World!

        editor.restore(history.undo());
        System.out.println(editor.getText()); // Hello

        editor.restore(history.redo());
        System.out.println(editor.getText()); // Hello World!
    }
}

마무리

예제를 보면 글자를 자동 저장하면서 되돌리기 앞으로 가기 같은 기능을 만들 때 사용하는 예제로도 사용할 수 있고, 적당한 상황에 쓰기에는 나쁘지 않은 방법 같습니다.

+ Recent posts