게시글

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

디자인 패턴(적응자, adapter)

안녕하세요. 이번 시간에는 적응자 패턴에 대해 알아보겠습니다! 적응자 패턴은 추상 팩토리나 빌더 패턴처럼 객체를 생성하는 패턴이 아닙니다. 기존에 있던 구조를 새 구조로 유연하게 전환하거나 새 구조에서 기존의 구조로 전환하는 데 사용하는 패턴입니다.

전 시간에 네로 황제를 모시는 루푸스 총독이 반란군 갈바를 공격하여 승리를 거뒀습니다. 문제는 루푸스 총독의 부하들이 오히려 루푸스 총독을 황제로 추대하려고 하는 것입니다. 빠르게 이 소식을 전해들은 원로원 정치인들 역시 네로 대신에 루푸스 총독을 추대하려고 하고 있습니다.

원로원에서는 투표로 황제를 추대하는데 현재의 시스템은 현재의 황제를 자동적으로 지지하도록 되어있습니다. 원로원 정치인들은 허겁지겁 루푸스를 추대하려고 시스템을 바꿉니다. 만약 루푸스가 황제가 되면 다시 원래의 시스템인 현 황제를 지지하는 시스템으로 돌아가려고 합니다. 간에 붙었다 쓸개에 붙었다 하는거죠. 이럴 때 적응자 패턴이 도움이 됩니다.

먼저 원하는 결과를 봅시다. 현재 시스템은 현 황제를 자동적으로 지지하는 시스템이고, 신규 시스템은 새 황제를 추대할 수 있게 하는 시스템입니다. 뒤의 인자만 바꾸면 시스템을 전환할 수 있게 만들고 싶습니다.

var senateSystem = new SenateSystem(currentAdapter); // 현재 시스템
var senateSystem = new SenateSystem(rufusAdapter); // 신규 시스템

위와 같이 하면 뒤에 currentAdapter냐 newAdapter냐에 따라 시스템을 교체할 수 있겠죠? 이제 내부 코드를 구현해봅시다.

var SenateSystem = (function() {
  function SenateSystem(adapter) {
    this.adapter = adapter;
  }
  SenateSystem.prototype.vote = function() {
    this.adapter.vote();
  };
  return SenateSystem;
})();
var currentAdapter = {
  vote: function() {
    console.log('현 황제를 계속 지지합니다');
  }
};
var rufusAdapter = {
  vote: function() {
    console.log('루푸스를 황제로 추대합시다');
  }
};

이제 시스템을 바꿔가며 투표해봅시다. 잘 보면 새 시스템과 이전 시스템의 메소드는 같을수록 좋습니다. 사용자가 시스템마다 다른 메소드를 외울 필요가 없으니까요.

senateSystem = new SenateSystem(currentAdapter);
senateSystem.vote(); // 현 황제를 계속 지지합니다.
senateSystem = new SenateSystem(rufusAdapter);
senateSystem.vote(); // 루푸스를 황제로 추대합시다.

원로원에서는 이렇게 시스템을 바꿔놓고 루푸스가 오기를 기다립니다. 그러나 루푸스는 겸손하게 황제 추대를 사양합니다. 그러자 원로원은 다급히 갈바를 황제로 추대합니다. 눈 깜짝할 사이에요.

var galbaAdapter = {
  vote: function() {
    console.log('갈바를 황제로 추대합시다');
  }
};
senateSystem = new SenateSystem(galbaAdapter);
senateSystem.vote(); // 갈바를 황제로 추대합시다.

정말 빠르게 시스템을 바꿨죠? 정리하면 적응자 패턴은 두 가지 이상의 구조에서 유연하게 전환하고 싶을 때 유용합니다. 뒤의 인자만 바꾸면 구조가 교체됩기 때문에 간단합니다. 다음 시간에는 복합체 패턴에 대해 알아보겠습니다.

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

댓글

4개의 댓글이 있습니다.
2년 전
function SenateSystem(adapter) {
this.adaptar = adapter;
}
SenateSystem.prototype.vote = function() {
this.adapter.vote();
}
var currentAdapter = {
vote: function() {
console.log('현 황제를 지지 합니다.');
}
}
senateSystem = new SenateSystem(currentAdapter);
senateSystem.vote(); // error 발생

=========에러=========
Uncaught TypeError: Cannot read properties of undefined (reading 'vote')
at SenateSystem.vote (\u003canonymous>:5:18)
at \u003canonymous>:1:14

왜 vote를 읽을수 없는걸까요 .. ?
2년 전
adaptar 오타니까요.
6년 전
나올 책 기대되네요. 나오길 기다릴께요
6년 전
ㅋㅋㅋ 예시랑 예제랑 너무 잘어울리네요
7년 전
왠지 Fn.apply , call 이랑 느낌이 비슷해 보입니다. 제가 맞나요?
Constructor를 조금 수정해서
senateSystem = new SenateSystem();
senateSystem.vote.call(currentAdapter);
senateSystem.vote.call(rufusAdapter);
이런식으로 다이나믹하게 call을 할 수 있을것 같은데,, 이 패턴과 비교해서어떤 장단점이 있을까요?
7년 전
비슷하긴 합니다. 단지 매번 함수를 호출할 때마다 call(currentAdapter)를 붙여줘야한다는 귀찮음이 있죠. 저는 call같은 것은 일회성으로 남의 메소드를 빌려올 때 주로 사용하고, 적응자 패턴은 자주 남의 메소드를 사용할 때 사용합니다.