Begavioral Patterns
구현 세부정보를 공개하지 않고 객체의 이전 상태를 복원할 수 있는 패턴
텍스트 편집기 앱을 상상해봅시다. 텍스트 수정 외에도 서식 지정, 이미지 삽입 등을 수행할 수 있습니다. 그럼 실행 취소는 어떨까요?
실행 취소를 구현하기 위해 작업을 수행하기 전에 모든 상태를 일부 저장소에 저장하고 나중에 작업을 되돌릴 때 최신 스냅샷을 가져와 모든 상태를 복원하게 됩니다.
하지만 모든 상태를 저장하기 위해선 모든 컨텐츠에 대한 접근 제한을 완화해야 합니다. 불행하게도 대부분의 필드는 외부에서 볼 수 없도록 비공개 상태입니다.
모두 공개를 했다고 가정해도 문제가 남아있습니다. 나중에 편집기 클래스를 리팩토링할 때 상태 복사를 담당하는 클래스 역시 변경해야 할 수 있습니다.
상태 스냅샷은 텍스트, 커서 좌표, 스크롤 위치 등 많은 값을 컨테이너에 넣어야 합니다. 보통 이런 컨테이너 역시 한 클래스의 객체를 사용하고 해당 클래스의 필드 역시 공개해야 합니다. 결국 편집기의 상태가 노출되어 편집기와 관련된 사항들에 취약하게 됩니다.
이러한 문제를 직면하지 않고 undo
를 구현할 수 있는 방법은 없을까요?
손상된 캡슐화가 문제❗️ 데이터를 수집하기 위해 다른 객체의 private
공간을 침범하게 됩니다.
Memento 패턴은 상태 스냅샷 생성을 해당 상태를 소유한 객체에 위임합니다. 외부에서 해당 객체에 상태를 복사하는 대신 편집기 클래스 자체가 스냅샷을 만들게 됩니다.
객체의 상태는 memento라는 특수 객체에 저장하도록 합니다. memento는 해당 객체를 생성한 객체를 제외하고는 접근할 수 없습니다. 대신 스냅샷의 메타데이터(생성 시간, 수행 작업 이름 등)를 인터페이스를 사용해 memento에서 가져올 수 있습니다.
이러한 제한을 이용하면 caretaker이라는 다른 객체에 memento를 저장할 수 있습니다. caretaker는 인터페이스를 통해서만 memento를 관리하기 때문에 memento 내부 상태는 변경할 수 없습니다. 또한 originator(= 편집기)는 memento 내부 필드에 접근할 수 있어 이전 상태를 복원할 수 있습니다.
편집기 앱 예제에서 caretaker 역할을 하는 클래스를 만들 수 있습니다. 사용자가 실행 취소를 트리거하면 가장 최근의 memento를 가져와 편집기로 전달하며 롤백을 요청합니다.
참고 링크
Memento