게시글

5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭
강좌37 - JavaScript - 8년 전 등록 / 7년 전 수정

디자인 패턴(빌더, builder)

안녕하세요. 이번 시간에는 빌더 패턴에 대해서 알아보겠습니다. 전 시간의 추상 팩토리 패턴은 여러 팩토리를 동시에 사용하고 싶을 때 사용했었죠. 빌더 패턴은 옵션이 많을 때 사용합니다. 로봇을 조립한다고 생각하시면 됩니다.

전 시간에 각지에서 반란이 일어났습니다. 갈바, 오토, 빈덱스, 비텔리우스는 갈바를 중심으로 연합을 맺었습니다. 반란을 일으킨 자들은 군단을 꾸려 로마로 진격합니다. 반대로 로마에서 네로는 반란군은 막으려 군단을 출격시킵니다. 독일 총독 루푸스가 진압에 앞장섭니다. 군단에는 리더와 부관, 병력들이 있겠죠? 그런데 어떤 군단은 부관이 없을 수도 있습니다. 이렇게 큰 유형은 같지만 세부적인 사항이 다를 때 빌더 패턴이 유용합니다.

이전 시간에 먼저 결과부터 생각하라고 그랬죠? 일단 원하는 결과부터 써봅시다. 아래처럼 하면 같은 군단의 개념이지만 서로 다른 옵션을 줄 수 있을 것 같습니다.

var galbaLegion = makeLegion('galba').setAdjutant(['otho', 'vindex', 'vitellius']).setArmy(8000).build();
var rufusLegion = makeLegion('rufus').setArmy(10000).build();

이렇게 두 군단을 만들 수 있습니다. 이제 내부 구현을 해볼까요?

var makeLegion = function(leader) {
  var adjutants = null;
  var army = 0;
  return {
    setAdjutant: function(list) {
      adjutants = list;
      return this;
    },
    setArmy: function(number) {
      army = number;
      return this;
    },
    build: function() {
      return {
        leader: leader,
        adjutants: adjutants,
        army: army
      };
    }
  };
};

결과를 보면 제대로 만들어진 것을 확인할 수 있습니다.

galbaLegion; // { leader: 'galba', adjutants: ['otho', 'vindex', 'vitellius'], army: 8000 }
rufusLegion; // { leader: 'rufus', adjutants: null, army: 10000 }

한 가지 개선하고 싶은 점은, 이렇게 만든 군단에 메소드를 추가하고 싶습니다. 예를 들면, 다른 군단을 공격한다는 등의 메소드를요. makeLegion 코드를 좀 수정합시다.

var Legion = (function() {
  function Legion(leader, adjutants, number) {
    this.leader = leader;
    this.adjutants = adjutants || null;
    this.number = number || 0;
  }
  Legion.prototype.attack = function(target) {
    console.log(this.leader + '가 ' + target.leader + '를 공격합니다');
  };
  return Legion;
})();
var makeLegion = function(leader) {
  var adjutants = null;
  var army = null;
  return {
    setAdjutant: function(list) {
      adjutants = list;
      return this;
    },
    setArmy: function(number) {
      army = number;
      return this;
    },
    build: function() {
      return new Legion(leader, adjutants, army);
    }
  }
};

다시 galbaLegion과 rufusLegion을 만들어주고 다음 코드를 실행해봅니다.

rufusLegion.attack(galbaLegion); // rufus가 galba를 공격합니다.

바뀐 점은 Legion을 따로 생성자 객체로 만들어 prototype을 사용할 수 있게 되었다는 거죠. 이렇게 빌더 패턴을 사용하면 손쉽게 옵션을 바꿔가며 객체를 만들 수 있습니다.

실제로 루푸스가 갈바 군단을 공격해 승리합니다. 여기서 갈바의 동맹인 프랑스 총독 빈덱스가 패배한 후 자결하죠. 갈바는 이에 흔들려서 잠시 주춤합니다.

다음 시간에는 적응자 패턴에 대해 알아보겠습니다!

조회수:
0
목록
투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.
5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭

댓글

5개의 댓글이 있습니다.
6년 전
java 개발하며 자주보던 패턴인데 javascript에도 적용할 수 있군요. 오히려 알면 알수록 java보다 어려운것 같아요. 두 예제 모두 this 활용 진짜 잘하셨네요.
7년 전
생성자 함수로 인스턴스화 된 객체는 메소드를 상속 받아 사용할 수 있자나요. 이때의 메소드는 빌더인거죠?
7년 전
아뇨. 객체를 만들어 내는 생성자 역할이 빌더입니다.
7년 전
군단을 만들 때 병력은 setArmy 를 이용해서 생성하고 build는 다른 메서드로 받은 인자를 return 만 시켜주는걸 보니
맨 마지막 예제의 makeLegion 함수의 build 메서드는 number 매개변수를 없애고 Legion 인스턴스 생성 인자에 number 대신 army가 들어가야 할거같습니다..
7년 전
아아 맞습니다. ㅋㅋ 1년간 아무도 지적을 안 해주셨다는게 더 소름이네요. 저도 1년만에 코드를 다시 보는데 부족한 게 많습니다. 감사합니다.
7년 전
makeLegion 함수에서 매개변수 leader 랑 같은이름 으로 변수 처리 하셨는데
그냥 매개변수그대로 쓰는게 좋은거 아닌가요?
어떤게 나은건지 다른 의견을 들은적이 있어서 제로님의 의견이 궁금합니다
7년 전
매개변수 그대로 쓰는 게 좋습니다.
8년 전
Region --> Legion 오타입니다
8년 전
앗 감사합니다!