본문 바로가기
까망 동네/디자인 패턴

[디자인 패턴] 메멘토 패턴 (Memento Pattern)

by 까망 하르방 2023. 11. 10.
반응형

🎈 메멘토 패턴 (Memento Pattern)

• 객체 상태를 저장/복원하는 디자인 패턴

• 스냅샷과 같은 기능으로 "실행 취소" 및 "다시 실행" 구현에 유용

 활용 예시: 텍스트 에디터, 게임 상태, 회원가입 양식, 데이터베이스 백업 등

• 디자인 패턴 중 행위 패턴에 해당된다.

 

💻 디자인 패턴(Design Pattern)이란?

👨‍💻 디자인 패턴(Design Pattern)이란? • SW 개발 방법 중에서도 구조적인 문제 해결에 목적을 둔다. • 알고리즘과 같이 특정 문제를 해결하는 Logic 형태보다는 특정 상황에 적용할 수 있는 방

zoosso.tistory.com

 

 

[예제코드]

#include <iostream>
#include <string>

class Character {
private:
    std::string name;
    int health;

public:
    Character(std::string name, int health) : name(name), health(health) {}

    void SetState(std::string name, int health) {
        this->name = name;
        this->health = health;
    }

    void ShowState() {
        std::cout << "이름: " << name << ", 체력: " << health << std::endl;
    }

    class Memento {
    private:
        std::string name;
        int health;

    public:
        Memento(std::string name, int health) : name(name), health(health) {}

        std::string GetName() {
            return name;
        }

        int GetHealth() {
            return health;
        }
    };

    Memento CreateMemento() {
        return Memento(name, health);
    }

    void RestoreFromMemento(Memento memento) {
        this->name = memento.GetName();
        this->health = memento.GetHealth();
    }
};

class Caretaker {
private:
    Character::Memento memento;

public:
    Caretaker() : memento("Default", 0) {}

    void SetMemento(Character::Memento memento) {
        this->memento = memento;
    }

    Character::Memento GetMemento() {
        return memento;
    }
};

int main() {
    Character character("까망", 100);
    Caretaker caretaker;

    // 상태 저장
    caretaker.SetMemento(character.CreateMemento());
    character.ShowState();

    // 상태 변경
    character.SetState("하르방", 50);
    character.ShowState();

    // 상태 복원
    character.RestoreFromMemento(caretaker.GetMemento());
    character.ShowState();

    return 0;
}

 

메멘토 디자인 패턴 예시

 

Character 클래스는 Memento 내부 클래스로 상태를 저장/복원한다.

Caretaker 클래스는 Memento를 보관하고 복원을 요청한다.


 

🎈 메멘토 패턴 장단점

+  상태 저장과 복원 분리:

 객체 내부 상태를 외부에서 접근하지 않고도 복원하기에

 객체 캡슐화와 데이터 은닉을 유지할 수 있다.

+ 상태 이력 관리: 객체의 상태를 여러 시점에서 저장하고 관리할 수 있다.

 → "실행 취소"와 "다시 실행"과 같은 기능 구현에 유용

+ 새로운 기능 추가와 변경시 안정성 확보

 

- 메모리 사용량 증가: 객체 상태 저장을 위한 추가 메모리 필요

- 복잡성 증가: 객체 상태 저장/복원 로직이 추가되므로 유지보수와 이해도가 어려워질 수 있다.

 

 

[예제코드]

#include <iostream>
#include <string>
#include <vector>

class TextEditor {
private:
    std::string text;

public:
    TextEditor() : text("") {}

    void SetText(const std::string& newText) {
        text = newText;
    }

    std::string GetText() const {
        return text;
    }

    class Memento {
    private:
        std::string savedText;

    public:
        Memento(const std::string& text) : savedText(text) {}

        std::string GetSavedText() const {
            return savedText;
        }
    };

    Memento CreateMemento() {
        return Memento(text);
    }

    void RestoreFromMemento(const Memento& memento) {
        text = memento.GetSavedText();
    }
};

class Caretaker {
private:
    std::vector<TextEditor::Memento> savedStates;

public:
    void AddMemento(const TextEditor::Memento& memento) {
        savedStates.push_back(memento);
    }

    TextEditor::Memento GetMemento(int index) {
        if (index >= 0 && index < savedStates.size()) {
            return savedStates[index];
        }
        // [에러 처리] 유효하지 않은 인덱스
        return TextEditor::Memento("");
    }
};

int main() {
    TextEditor editor;
    Caretaker caretaker;

    // 텍스트 편집 및 상태 저장
    editor.SetText("까망 하르방");
    caretaker.AddMemento(editor.CreateMemento());

    editor.SetText("까망 포레스트");
    caretaker.AddMemento(editor.CreateMemento());
   
    editor.SetText("@gm.snack");
    caretaker.AddMemento(editor.CreateMemento());

    // 현재 상태 출력
    std::cout << "현재: " << editor.GetText() << std::endl;

    // 이전 상태로 복원
    int restoreIdx = 0;
    editor.RestoreFromMemento(caretaker.GetMemento(restoreIdx));
    std::cout << "[" << restoreIdx << "] 상태로 변경: " << editor.GetText() << std::endl;

    restoreIdx = 1;
    editor.RestoreFromMemento(caretaker.GetMemento(restoreIdx));
    std::cout << "[" << restoreIdx << "] 상태로 변경: " << editor.GetText() << std::endl;

    return 0;
}

 

메멘토 디자인 패턴 예시

 

객체 상태를 caretake 객체에 저장하여

원하는 시점의 상태로 복원할 수 있다.

반응형

댓글