안녕하세요. 이번 시간에는 복합체 패턴에 대해 알아보겠습니다! 복합체 패턴은 트리 구조에 사용되는 패턴인데요. 사실 자바스크립트를 하는 사람이면 한 번 쯤은 써본 패턴일 겁니다. 써본 적이 없다고요? 써봤다니까요!
바로 jQuery가 복합체 패턴을 따릅니다. jQuery는 하나의 태그를 선택하든, 여러 개의 태그를 동시에 선택하든 모두 같은 메소드를 쓸 수 있습니다. 예를 들면, $('#zero')로 하나의 태그를 선택할 수도 있고, $('p')로 모든 p 태그를 선택할 수도 있습니다. 하지만 개수와 상관 없이 모두 attr이나 css같은 메소드를 사용할 수 있습니다. 이제 직접 복합체 패턴을 사용한 객체를 만들어봅시다.
원로원에 의해 황제에 추대된 갈바는 이제 다시 네로를 치려고 로마로 진격합니다. 갈바의 업적 중 하나는 잘 편제된 군단(Legion)을 가지고 있었다는 겁니다. 로마 군단은 군단 아래에 10개의 대대(Cohort)가 있습니다. 한 개의 대대 아래에는 6개의 중대(Century), 한 개의 중대 아래에는 10개의 분대(Contuberium)가 있죠. 한 분대가 8명으로 이루어져 있으니까 총 군단의 군사 수는 8*10*6*10 = 4800명 정도 되겠네요. (실제로는 기병도 있고 해서 더 많습니다...)
각 단위(군단, 대대, 중대, 분대)는 모두 병력의 수와 리더의 이름을 알려주는 메소드를 가지고 있습니다. 한 번 코드로 만들어보죠. 분대까지 가기엔 너무 수가 많으니까 중대부터 시작합시다.
var Century = (function() {
function Century(leader) {
this.leader = leader;
}
Century.prototype.getLeader = function() {
return this.leader;
};
Century.prototype.getNumber = function() {
return 80; // 중대는 80명
}
return Century;
})();
var Cohort = (function() {
function Cohort(leader) {
this.leader = leader;
this.centuries = [];
}
Cohort.prototype.getLeader = function() {
return this.leader;
};
Cohort.prototype.getNumber = function() {
var sum = 0;
this.centuries.forEach(function(century) {
sum += century.getNumber();
});
return sum;
};
Cohort.prototype.addCentury = function(century) {
this.centuries.push(century);
return this;
};
return Cohort;
})();
var Legion = (function() {
function Legion(leader) {
this.leader = leader;
this.cohorts= [];
}
Legion.prototype.getLeader = function() {
return this.leader;
};
Legion.prototype.getNumber = function() {
var sum = 0;
this.cohorts.forEach(function(cohort) {
sum += cohort.getNumber();
});
return sum;
}
Legion.prototype.addCohort = function(cohort) {
this.cohorts.push(cohort);
return this;
};
return Legion;
})();
이렇게 군단, 대대, 중대를 만들었는데요. 잘 보면 군단과 대대에 하부 조직을 추가하는 것을 제외하고는 메소드가 다 같습니다. getLeader과 getNumber이 공통이죠. 위의 코드를 바탕으로 실제 코드를 짜봅시다.
var century1 = new Century('Maximus');
var century2 = new Century('Tiberius');
var century3 = new Century('Lukius');
var century4 = new Century('Marcus');
var century5 = new Century('Pompeius');
var century6 = new Century('Zero');
var cohort1 = new Cohort('Vitellius');
var cohort2 = new Cohort('Otho');
var legion = new Legion('Galba');
cohort1.addCentury(century1).addCentury(century2).addCentury(century3);
cohort2.addCentury(century4).addCentury(century5).addCentury(century6);
legion.addCohort(cohort1).addCohort(cohort2);
뭔가 로마인이 아닌 사람이 한 명 있는 것 같은데... 그냥 넘어가죠. 이렇게 군단 아래 두 대대와, 대대 아래 세 중대를 편성했습니다. 군단의 메소드를 호출해볼까요?
legion.getLeader(); // Galba
legion.getNumber(); // 480
cohort1.getNumber(); // 240
군단에 480명밖에 없네요... 이게 다 귀찮아서 코드를 덜 친 제 잘못입니다. 하지만 메소드는 잘 작동하네요. 군단의 메소드를 호출하면 알아서 중대부터 해서 인원 수를 다 더해줍니다. 편하죠?
다음 시간에는 병사 개개인을 객체로 만드는 플라이급 패턴을 알아봅시다.