Java/Design Pattern

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

민돌v 2023. 4. 12. 08:40
728x90
(인프런) 코딩으로 학습하는 GoF의 디자인 패턴 - 백기선, 강의를 보고 정리한 글입니다.
코드는 GitHub 에 있습니다

 

#1. 객체 생성 관련 패턴

#2. 구조 관련 패턴

 

#3. 행동 관련 패턴

 

 

 


✔️ 메멘토 패턴이란 (Memento Pattern)

캡슐화를 유지하면서 객체 내부 상태를 외부에 저장하는 방법.
  • 👏🏻  메멘토 패턴이란, 객체의 상태정보를 가지는 클래스를 따로 생성하여 객체 내부의 상태를 외부에 저장해놓고 저장해놓은 정보를 복원시킬 수 있도록 해주는 패턴입니다.
  • "특정 시점"의 "객체의 상태" 를 외부에 저장하기 위새너는 객체 내부의 상태가 외부에 온전히 노출되어야하지만 메멘토 패턴을 사용한다면 캡슐화 상태를 지키면서 복원시킬 수 있습니다.
  • 즉, 메멘토 패턴은 내부 상태를 전부 외부에 노출하지 않으면서 객체 상태를 외부에 저장했다가 해당 상태로 다시 복구시키는데 목적을 가집니다.

 

메멘토 패턴

 

메멘토 패턴은 굉장히 단순한 흐름을 가집니다.

보통, "게임에서 저장된 시점 불러오기", 바둑에서의 "무르기" 등등 과 같은 상황에 사용이 될 수 있습니다.

 

 


✔️ 메멘토 패턴 예시

1) 메멘토 패턴 적용 전

  • 먼저 특정한 상태값을 가지는 Game 객체를 선언해 주었습니다.
  • 객체의 상태값은 계속 변동되고, 특정한 시점을 외부에 저장해 두었다가 복원시키고자 합니다.
@Getter
@Setter
public class Game {

    private int blueTeamScore = 0;
    private int redTeamScore = 0;

}

 

  • 단순하게 구현하자면 이렇게 특정 시점의 상태값을 외부에 저장시켰다가 복원시킬 수 있습니다.
public class Client {

    public static void main(String[] args) {
        Game game = new Game();
        game.setRedTeamScore(10);
        game.setBlueTeamScore(20);

        //점수 저장 → 클라이언트가
        int redTeamScore = game.getRedTeamScore();
        int blueTeamScore = game.getBlueTeamScore();

        //값이 변경되었다가
        game.setRedTeamScore(12);
        game.setBlueTeamScore(22);

        //저장된 시점으로 복원
        Game restoreGame = new Game();
        restoreGame.setRedTeamScore(redTeamScore);
        restoreGame.setBlueTeamScore(blueTeamScore);
    }
}
  • 📌 하지만 이러한 방법은 특정 객체의 상태값이 어떤걸 가지고있는지 온전히 전부 외부에 노출되고 있습니다.
  • 객체 상태정보를 은닉하기 위해 접근제어자를 private 로 사용한 의미가 없어집니다.

 

2) 메멘토 패턴 적용 후

  • 이러한 문제점을 해결하기 위해, 저장하고자 하는 객체의 상태값을 알고있는 별도의 객체로 관리합니다.
  • 결국 해당객체(Memento) 가 저장하고자하는 객체 (Origintor)의 상태를 알고있어야하지만
  • 외부 클라이언트 여기저기서 객체의 상태값을 부분별학게 알고있는 단점을 줄일 수 있습니다.

 

Memento 객체

  • 👏🏻 단, 이러한 상태를 저장하고 있는 객체는 온전한 값 불변 객체로써 상태가 변경되어서는 안됩니다.
//불변해야함
@Getter
public final class GameSave {

    private final int blueTeamScore;
    private final int redTeamScore;

    public GameSave(int blueTeamScore, int redTeamScore) {
        this.blueTeamScore = blueTeamScore;
        this.redTeamScore = redTeamScore;
    }
}

 

Orign 객체

  • 원본 객체에서 특정 상태값을 저장할 시, Memento 객체를 반환합니다.
@Getter
@Setter
public class Game {

    private int redTeamScore;
    private int blueTeamScore;

    public GameSave save() {
        return new GameSave(this.blueTeamScore, this.redTeamScore);
    }

    public void restore(GameSave gameSave) {
        this.blueTeamScore = gameSave.getBlueTeamScore();
        this.redTeamScore = gameSave.getRedTeamScore();
    }
}



public class Client {

    public static void main(String[] args) {
        Game game = new Game();
        game.setBlueTeamScore(10);
        game.setRedTeamScore(20);

        GameSave save = game.save();

        game.setBlueTeamScore(12);
        game.setRedTeamScore(22);

        //저장된 시점으로 복원
        game.restore(save);

    }
}

 


✔️ 메멘토 패턴 장단점

장점

  • 캡슐화를 지키면서 상태 객체의 상태 스냅샷을 만들 수 있다.
  • 객체 상태를 저장하고 또는 복원하는 역할을 CareTaker(복수의 Memento 상태를 유지해주는 객체 - 예제에서는 구현하지 않음)에게 위임할 수 있다.
  • 객체 상태가 바뀌어도 클라이언트 코드는 변경되지 않는다.

 

단점

  • Mementor를 자주 생성하는 경우 메모리 사용량에 많은 영향을 줄 수 있다.
  • 마찬가지로, Origin 객체의 저장해얄 상태정보가 커서 Memento 객체가 커지면 많은 메모리를 잡아먹을 수 있다.

 

 

 

 

 

 

반응형