ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [디자인패턴] 메멘토패턴
    기타/북스터디 2023. 1. 29. 08:58

    1. 메멘토패턴(memento pattern)이란?

    메멘토패턴은 객체 내부의 상태를 외부에 저장을 하고 저장된 상태를 다시 복원하고자 할 때에 사용하는 패턴이다.

    메멘토패턴을 사용함으로써 객체의 모든 정보를 외부로 노출시키지 않고 캡슐화를 지킬 수 있다.

    출처: 코딩으로 학습하는 GOF의 디자인 패턴(인프런강의, 백기선님)

    Originator는 본래의 상태를 가지고 있고 상태를 저장하고 복원하고 싶어하는 객체이다.

    Memento는 immutable한 객체로 일정 시점의 Originator 내부정보를 가지고 있다.

    CareTaker는 Originator의 내부정보를 Memento type으로 가지고 있고 복원을 할 수 있는 객체이다.

     

     

     

    2. 메멘토패턴을 사용하지 않은 코드

    게임의 현재 스테이지와 캐릭터의 정보를 가지고 있는 클래스가 있다고 가정해보자.

    public class Game {
    
      private int stage;
      private Character character;
      
      public int getStage() {
        return stage;
      }
      
      public void setStage(int stage) {
        this.stage = stage;
      }
      
      public Character getCharacter() {
        return character;
      }
      
      public void setCharacter(Character character) {
        this.character = character;
      }
    }

     

    그리고 게임이 진행 중에 이전 시점으로 돌리는 상황을 가정한 클라이언트를 코드를 봐보자.

    public class Client {
    
      public static void main(String[] args) {
        Game game = new Game();
        game.setStage(10);
        game.setCharacter(new Character());
        
        int stage = game.getStage();
        Character character = game.getCharacter();
        
        Game restoredGame = new Game();
        restoredGame.setStage(stage);
        restoredGame.setCharacter(character);
      }
    }

    위와 같은 코드의 문제점은 아래와 같다.

    1. 캡슐화가 깨지게 된다.

    - 클라이언트가 게임이 구성하는 요소가 무엇인지 알게 된다.

     

    2. 클라이언트가 Game객체에 의존하게 된다.

    - Game의 멤버가 바뀜에 따라 클라이언트 코드가 바뀌어야한다.

     

     

     

    3. 메멘토패턴을  적용해보자.

    먼저, 메멘토 클래스를 만들어보자.

    public final class GameSave {
    
      private final int stage;
      private final Character character;
      
      public GameSave(int stage, Character character) {
        this.stage = stage;
        this.character = character;
      }
      
      public int getStage() {
        return stage;
      }
    
      public Character getCharacter() {
        return character;
      }
    }

     

    그리고 Originator인 Game 클래스에서는 메멘토를 사용하여 저장하고 복원할 수 있는 메서드를 만들어주자.

    public class Game {
    
      private int stage;
      private Character character;
      
      public int getStage() {
        return stage;
      }
      
      public void setStage(int stage) {
        this.stage = stage;
      }
      
      public Character getCharacter() {
        return character;
      }
      
      public void setCharacter(Character character) {
        this.character = character;
      }
      
      public GameSave save() {
        return new GameSave(this.stage, this.character);
      }
      
      public Game restore(GameSave gameSave) {
        this.stage = gameSave.getStage();
        this.character = gameSave.getCharacter();
      }
    }

     

    이렇게 Originator와 Memento를 만들어주면 클라이언트 코드는 아래와 같이 변경된다.

    public class Client {
    
      public static void main(String[] args) {
        Game game = new Game();
        game.setStage(10);
        game.setCharacter(new Character(1, "memento"));
    
        GameSave save = game.save();
    
        game.setStage(12);
        game.setCharacter((new Character(15, "visitor")));
    
        game.restore(save);
    
        System.out.println(game.getStage());
        System.out.println(game.getCharacter().getLevel());
        System.out.println(game.getCharacter().getName());
      }
    }

    실행을 시켜보면 아래와 같이 game의 이전 정보가 보여지는 것을 볼 수 있다.

    댓글

Designed by Tistory.