Language/Design Pattern

[Design Pattern] 행동패턴 - Memento

JB1104 2023. 11. 8. 15:49
728x90
반응형
SMALL

 

메멘토(Memento) 패턴

  • 캡슐을 유지하면서 객체 내부 상태를 외부에 저장하는 방법
  • 객체의 상태정보를 가지는 클래스를 따로 생성하여 객체 내부의 상태를 외부에 저장해 놓고 저장해 놓은
  • 정보를 복원시킬 수 있도록 해주는 패턴
  • '특정 시점'의 '객체의 상태'를 외부에 저장하기 위해서는 객체 내부의 상태가 외부에 온전히 노출되어야 하지만
  • 메멘토 패턴을 사용한다면 상태를 지키면서 복원시킬 수 있다.
  • 즉, 메멘토 패턴은 내부 상태를 전부 외부에 노출하지 않으면서 객체 상태를 외부에 저장했다가 해당 상태로 다시 복구시키는 목적이 있다. (저장된 시점 불러오기와 같은 상태를 다시 불러올 때 사용)

 

구조

  • Originator : 상태를 저장하고 복원하려는 객체
  • Memento :  immutable 한 객체로 일정 시점의 Originator 상태를 저장하는 객체
  • Caretaker : Originator 상태를 Memento 타입으로 저장하고 관리하는 객체


메멘토(Memento) 패턴 적용 전

 

  • 특정한 상태값을 가지는 Game 객체를 선언
  • 객체의 상태값은 계속 변경되고, 특정한 시점을 외부에 저장해 두었다가 복원시키고자 한다.
@Getter
@Setter
public class GameBefore {
    private int blueTeamScore = 0;
    private int redTeamScore = 0;
}

 

    @Test
    void test1() {
        GameBefore game = new GameBefore();
        game.setBlueTeamScore(10);
        game.setRedTeamScore(20);

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

        // 값이 변경됨
        game.setBlueTeamScore(15);
        game.setRedTeamScore(28);

        // 저장된 시점으로 복구
        GameBefore restoreGame = new GameBefore();
        restoreGame.setBlueTeamScore(blueTeamScore);
        restoreGame.setRedTeamScore(redTeamScore);
        System.out.println("블루팀 점수 : " + restoreGame.getBlueTeamScore());
        System.out.println("레드팀 점수 : " + restoreGame.getRedTeamScore());
    }

 
특정 객체의 상태값이 어떤 걸 가지고 있는지 외부에 전부 노출되고 있다.
객체 상태정보를 은닉하기 위해 접근제어자를 private으로 사용한 의미가 없어진다.


메멘토(Memento) 패턴 적용 후

  • 저장하고자 하는 객체의 상태값을 알고 있는 별도의 객체를 만들어서 관리
  • Memento가 저장하고자 하는 객체(Originator)의 상태를 알고 있어야 한다
  • 외부 클라이언트에서 객체의 상태값을 알고 있는 단점을 줄일 수 있다

 

  • Memento상태값이 변경되어서는 안 되기 때문에 불변 객체이어야 한다.
@Getter
public class GameSave {
    private final int blueTeamScore;
    private final int redTeamScore;

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

 

  • Originator 객체에서 특정 상태값을 저장할 시, Memento 객체를 반환
@Getter
public class GameSave {
    private final int blueTeamScore;
    private final int redTeamScore;

    public GameSave(int blueTeamScore, int redTeamScore) {
        this.blueTeamScore = blueTeamScore;
        this.redTeamScore = redTeamScore;
    }
}
 @Test
    void test2() {
        Game game = new Game();
        // 값 세팅
        game.setBlueTeamScore(30);
        game.setRedTeamScore(15);

        // 저장
        GameSave save = game.save();
        // 변경
        game.setBlueTeamScore(18);
        game.setRedTeamScore(10);

        // 복원
        game.restore(save);
        System.out.println("블루팀 점수 : " + game.getBlueTeamScore());
        System.out.println("레드팀 점수 : " + game.getRedTeamScore());
    }

 

블루팀 점수 : 30
레드팀 점수 : 15

메멘토(Memento) 패턴

장점

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

단점

  • Memento를 자주 생성하는 경우 메모리 사용량에 많은 영향을 줄 수 있다.
  • Originator 객체의 저장해야 할 상태정보가 커서 Memento 객체가 커지면 많은 메모리를 잡아먹을 수 있다.
728x90
반응형
LIST