Command Pattern을 이용한 Undo/Redo 구현

최정은·2020년 12월 21일
0

Undo&Redo 구현

이제 undo&redo 구현의 핵심인 CommandManager를 설명해보겠다.

src/common/CommandManager.ts

class CommandManager {
  public undoList: Command[];
  public redoList: Command[];

  constructor() {
    this.undoList = []
    this.redoList = []
  }

  execute(command: Command) {
    command.execute();
    this.undoList.push(command);
    this.redoList = [];
    storeChannel.publish(StoreChannelType.EDIT_TOOLS_CHANNEL, null);
  }

  undo() {
    if (this.undoList.length > 0) {
      const command: Command | undefined = this.undoList.pop();
      if (command) {
        this.redoList.push(command);
        command.undo();
        storeChannel.publish(StoreChannelType.EDIT_TOOLS_CHANNEL, null);
      }
    }
  }

  redo() {
    if (this.redoList.length > 0) {
      const command: Command | undefined = this.redoList.pop();
      if (command) {
        this.undoList.push(command);
        command.execute();
        storeChannel.publish(StoreChannelType.EDIT_TOOLS_CHANNEL, null);
      }
    }
  }

}

undoList와 redoList 변수를 선언한다.
CommandManager Class에 존재하는 함수에 대해 설명하자면

  • execute(command: Command)

    커맨드를 불러와서 실행시킨다. 해당 커맨드가 가지고 있는 execute 함수를 실행시킨다.

    그런 뒤 나중의 undo 기능을 실행할때를 대비하여 생성자에 적어뒀던 this.undoList에 커맨드를 저장해 놓는다.

    해당 커맨드가 수행이되면 redo의 기능이 초기화되기 때문에 this.redoList를 초기화시킨다.

  • undo()

    undo를 실행할때 undoList에 저장됐던 command를 꺼내어 redoList에 push 해준다.

    그런 후 꺼내온 command의 undo 함수를 실행한다.

  • redo()

    redoList에서 command를 꺼내오고 그 command를 undoList에 넣은 다음, command의 execute함수를 실행한다.

  • 공통적으로 각 함수의 마지막에서 state값이 변경됐음을 알리는 publish 함수를 호출한다.

클라이언트 기반 웹 음성 편집기 프로젝트에서 사용된 커맨드 구조는 다음과 같다.

  • CommandManager

    undoList와 redoList를 변수로 두며 execute 함수가 실행될때 해당 command를 undoList에 넣고 command의 execute 함수를 실행한다. 이때 실행한 후엔 redo를 할 수 없기때문에 redoList를 빈 배열로 초기화한다.

    undo 함수가 실행될땐 undoList에서 pop을 한 후 해당 command를 redoList에 넣어준다. 그런 후 꺼낸 command의 undo 함수를 실행한다.

    redo 함수가 실행될땐 redoList에서 command를 pop한 후 해당 command를 undoList에 넣어준다. 그런 후 꺼낸 command의 execute 함수를 실행한다.

  • DeleteCommand

    해당 파일과 같이 Command가 붙어있으면 command를 나타내는 파일이다.

  • CommandController

    커맨드를 실행시킨다. 예를 들어 client에서 트랙 삭제 기능을 사용하고싶을때 CommandController에 있는 executeDeleteTrackCommand를 호출하여 커맨드를 실행시킬 수 있다.

0개의 댓글