본문 바로가기

설계

[디자인 패턴] 메멘토 패턴 (Memento Pattern) - python 예제 코드

Memento 패턴은 객체의 상태를 저장하고, 나중에 복원하기 위한 패턴입니다. 이 패턴은 객체의 상태를 저장하는 Memento 객체와, 객체의 상태를 생성하는 Originator 객체, 그리고 Memento 객체를 관리하는 Caretaker 객체로 구성됩니다. 이 패턴을 사용하면 객체의 상태를 유지하면서, 상태를 수정하고 롤백하는 기능을 제공할 수 있습니다.

1. 예제 코드

예를 들어, 텍스트 에디터를 구현한다고 가정해봅시다. 이 때, 에디터의 상태는 사용자가 입력한 텍스트, 커서의 위치, 편집 모드 등이 될 수 있습니다. 이러한 상태를 저장하고 복원하기 위해 Memento 패턴을 사용할 수 있습니다.

다음은 Python으로 구현한 Memento 패턴 예제 코드입니다.

class Editor:
    def __init__(self):
        self.text = ""
        self.cursor_position = 0
        self.edit_mode = "insert"

    def insert(self, text):
        self.text = self.text[:self.cursor_position] + text + self.text[self.cursor_position:]
        self.cursor_position += len(text)

    def delete(self, length):
        self.text = self.text[:self.cursor_position] + self.text[self.cursor_position+length:]
        
    def save(self):
        return EditorState(self.text, self.cursor_position, self.edit_mode)

    def restore(self, state):
        self.text = state.text
        self.cursor_position = state.cursor_position
        self.edit_mode = state.edit_mode


class EditorState:
    def __init__(self, text, cursor_position, edit_mode):
        self.text = text
        self.cursor_position = cursor_position
        self.edit_mode = edit_mode


class History:
    def __init__(self):
        self.states = []

    def push(self, state):
        self.states.append(state)

    def pop(self):
        return self.states.pop()

editor = Editor()
history = History()

editor.insert("Hello, ")
editor.insert("World!")
history.push(editor.save())

editor.delete(6)
history.push(editor.save())

print(editor.text) # 출력: Hello, World!
editor.restore(history.pop())
print(editor.text) # 출력: Hello, World!
editor.restore(history.pop())
print(editor.text) # 출력: Hello,


위 코드에서 Editor 클래스는 상태를 가지고 있는 클래스입니다. insert 메소드는 에디터에 텍스트를 삽입하고, delete 메소드는 에디터의 텍스트를 삭제합니다. save 메소드는 에디터의 현재 상태를 저장하는 Memento 객체인 EditorState 객체를 반환합니다. restore 메소드는 EditorState 객체를 인자로 받아, 에디터의 상태를 복원합니다.

History 클래스는 Memento 객체를 관리하는 Caretaker 역할을 합니다. push 메소드는 에디터의 현재 상태를 History 객체에 추가합니다. pop 메소드는 History 객체에서 가장 최근에 저장된 EditorState 객체를 반환합니다.

위 예제에서는 에디터에 텍스트를 삽입하고, 텍스트를 삭제하는 동작을 수행한 후, save 메소드를 호출하여 현재 상태를 Memento 객체로 저장합니다. 이렇게 저장된 상태는 History 객체에 추가됩니다. 이후, restore 메소드를 사용하여 에디터의 이전 상태를 복원할 수 있습니다. 이를 통해, 사용자가 실수로 텍스트를 삭제한 경우에도 이전 상태로 되돌릴 수 있습니다.

위 예제에서는 상태를 저장하는 Memento 객체가 EditorState 클래스이지만, 실제로는 보다 복잡한 객체를 저장할 수도 있습니다. 또한, History 클래스에서는 저장된 상태를 리스트로 관리하고 있지만, 보다 복잡한 구조를 사용하여 상태를 관리할 수도 있습니다. 이 패턴은 상태를 저장하고 복원하는 기능을 제공하는 것이 주요 목적이기 때문에, 구현 방법은 다양하게 변형할 수 있습니다.

2. 장점

  • 객체의 상태를 저장하고 복원할 수 있으므로, 객체의 상태를 관리하기 쉬워집니다.
  • 객체의 상태를 수정하는 동작을 수행하기 전에 Memento 객체를 생성하여 상태를 저장하므로, 롤백 기능을 구현하기 용이해집니다.
  • 객체의 내부 상태를 외부에 노출하지 않고, Memento 객체를 통해 상태를 관리하므로 캡슐화가 강화됩니다.

3. 단점

  • Memento 객체를 생성하고 관리하기 위한 코드가 추가로 필요합니다.
  • Memento 객체가 상태를 저장하고 있기 때문에, 메모리 사용량이 증가할 수 있습니다. 대부분의 언어에서 Memento 객체를 직렬화하여 디스크에 저장할 수 있지만, 이 경우 파일 입출력 등이 추가로 필요해지므로 성능에 영향을 줄 수 있습니다.
  • Memento 객체의 저장 방식에 따라 상태 복원이 제대로 이루어지지 않을 수 있습니다. 예를 들어, 객체의 상태가 매우 복잡하고, Memento 객체가 모든 상태 정보를 가지고 있지 않을 경우, 상태 복원이 정확하게 이루어지지 않을 수 있습니다.

4. 결론

따라서, Memento 패턴은 객체의 상태를 저장하고, 복원하기 위한 유용한 패턴이지만, 상황에 따라서는 다른 패턴을 사용하는 것이 더 적합할 수 있습니다.