게시글

강좌43 - JavaScript - 3년 전 등록

디자인 패턴(명령, command)

조회수:
0

안녕하세요. 이번 시간에는 명령 패턴에 대해 알아보겠습니다. 명령 패턴은 이름 그대로 명령을 내리는 패턴입니다. 퍼사드 패턴 시간에 갈바가 군단에게 명령을 내리는 것 같이요. 다른 점은 명령이 독립적으로 있기 때문에 얼마든지 새로운 명령을 추가할 수 있다는 점입니다. 또한 undo 메소드를 만들어서 잘못된 명령을 내렸을 때 이전으로 되돌릴 수 있죠. 코드로 보겠습니다.

오토는 갈바를 암살하고 황제의 자리에 올랐지만 그에게는 어두운 미래가 다가오고 있었습니다. 바로 오토가 갈바를 암살하던 때, 비텔리우스는 독일의 군단을 이끌고 로마로 진격하고 있었죠. 오토는 그 사실을 몰랐고요. 때를 참 잘못 탔습니다. 비텔리우스는 휘하 군단에게 로마를 공격하라는 명령을 내립니다. 비텔리우스는 매우 게을렀기 때문에 직접 전술을 짜지 않고, 총사령관인 카이키나가 전술을 짜면 최종 승인만 내렸습니다.

var Vitellius = (function() {
  function Vitellius() {}
  Vitellius.prototype.approve = function(commander) {
    commander.execute();
  };
  return Vitellius;
})();
var Commander = (function() {
  function Commander() {
    this.commands = [];
  }
  Commander.prototype.execute = function() {
    this.commands.forEach(function(command) {
      command();
    });
  };
  Commander.prototype.do = function(command, args) {
    this.commands.push(function() {
      command.call(null, args);
    });
  };
  Commander.prototype.undo = function() {
    this.commands.pop();
  };
  return Commander;
})();
var strategy = {
  climbAlps: function() {
    console.log('알프스를 오릅니다');
  },
  prepareSupply: function(number) {
    console.log('보급품을 ' + number + '만큼 준비합니다');
  },
  attackRome: function() {
    console.log('로마를 공격합니다');
  },
};
var vitellius = new Vitellius();
var caecina = new Commander();
caecina.do(strategy.prepareSupply, 5000);
caecina.undo(); // prepareSupply 취소
caecina.do(strategy.prepareSupply, 10000);
caecina.do(strategy.climbAlps);
caecina.do(strategy.attackRome);
vitellius.approve(caecina); // 보급품을 10000만큼 준비합니다. 알프스를 오릅니다. 로마를 공격합니다.

비텔리우스보다 Commander 생성자에 더 주목해주시기 바랍니다. Commander 생서자는 명령을 받거나 되돌리고 최종적으로 비텔리우스의 승인을 받아 명령을 실행합니다. 보통 명령 패턴에서는 한 번에 몰아서 실행하지 않고 그 때 그 때 바로 실행합니다. 하지만 실행 취소를 하는 예시를 들기 위해 조금 수정했습니다.

나중에 명령을 더 추가하고 싶으면 strategy 객체에 추가하면 됩니다. Commander는 명령을 총체적으로 관리하는 객체이고 strategy는 명령을 모아둔 객체입니다. 비텔리우스는 사용자라고 생각하면 됩니다. 사용자가 어떤 동작을 하면(위의 코드처럼 approve 함수를 호출한다든지, 버튼에 이벤트리스너를 연결한 후 버튼을 누른다든지) Commander는 명령을 실행하는 겁니다.

다음 시간에는 책임 연쇄 패턴에 대해서 알아보겠습니다!

투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.

댓글

2개의 댓글이 있습니다.
일 년 전
실무에선 Command에서 바로 execute 해도 될것 같은데.. 과하다는 느낌도 조금 나네요. 물론 패턴은 기능을 분리하여 충실히 제 역할을 하고 있어 보여요. 그나저나 call이 나왔네요. 이번참에 call에 대해 정확히 알면 좋겠네요.
일 년 전
call은 그냥 함수 호출하는 기능이라 별게 없습니다. 특이한 점이라 하면 this를 바꿔줄 수 있다는 점 정도겠네요.
3년 전
?두번째 문단 7번 라인에 command() 요고는 어디있는거에요??
3년 전
forEach(function(command) <= 이 부분에서 제공되는 매개변수입니다. 이 매개변수는 this.commands.push 하는 부분에서 인자로 제공됩니다.
3년 전
아이고 저기 매개변수가 있었네요 ㅠㅠ 바쁜시간 뺏어 죄송합니다! 답변 감사드려요!