Adapter Pattern 어댑터 패턴을 액션스크립트로 컨버팅 – Head First Design Pattern
by 세계의끝 on 5.14, 2009, under Design Pattern
제가 참여하고 있는 스터디에서 교재로 사용하고 있는 오라일리/한빛출판사에서 발간된 Head First Design Pattern 입니다. 스터디에 대한 이해도를 높이고자 어댑터 패턴에 관한 자바 코드를 액션스크립트 코드로 컨버팅해 보았습니다.
책에는 어댑터 패턴을 이렇게 정의하고 있습니다.
“어댑터 패턴(Adapter Pattern) – 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다. 어탭터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있습니다.”
호스트코드에서 어떤 특정한 구상 클래스를 인터페이스를 통해 사용하고 있는 상황에서, 새로운 구상 클래스의 요건이 생겨서 제 3의 클래스가 생겼습니다. 이 때 호스트코드와 인터페이스의 코드는 변경하지 않고 (게다가 동일한 사용 방법으로) 제 3의 구상클래스의 메소드도 추가 사용할 수 있도록 해주는 패턴이라 할 수 있겠습니다.
IDuck 인터페이스 입니다. 책에서는 Duck 이지만 인터페이스임을 확실히 하기 위해 Duck 앞에 I를 붙였습니다.
0 1 2 3 4 5 6 7 | package { public interface IDuck { function quack ():void; function fly ():void; } } |
IDuck 을 구상하는 MallardDuck(물오리) 클래스 입니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | package { public class MallardDuck implements IDuck { public function quack():void { trace( "꽥!" ) } public function fly():void { trace( "날고 있어요~" ) } } } |
새로 등장한 ITurkey (칠면조) 인터페이스 입니다.
0 1 2 3 4 5 6 7 | package { public interface ITurkey { function gobble():void; function fly():void; } } |
ITurkey 인터페이스를 구상하는 WildTurkey 클래스 입니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package { public class WildTurkey implements ITurkey { public function gobble():void { trace( "골골~" ) } public function fly():void { trace( "조금밖에 못날아요" ) } } } |
이렇게 두개의 구상 클래스[01] 는 각자 하는 일이 다르지만 어떠한 요구에 의해 호스트코드에서 WildTurkey 를 MallardDuck 과 동일하게 사용해야 하는 경우가 생겨버렸습니다.
이런경우에 아래와 같이 IDuck 인터페이스를 구현한 TurkeyAdapter 클래스를 이용해 ITurkey 인터페이스를 구상한 WildTurkey 객체를 감싸서 MallardDuck처럼 보이도록 변장을 시킬 수 있습니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package { public class TurkeyAdapter implements IDuck { private var turkey:ITurkey; public function TurkeyAdapter ( $turkey:ITurkey ) { this.turkey = $turkey } public function quack():void { turkey.gobble(); } public function fly():void { for ( var i:int = 0; i < 5; i++ ) { //칠면조가 어댑터로 실행된 것을 구분하기 위해 오리흉내(5번 짧게 날기) 를 냅니다. turkey.fly(); } } } } |
아래와 같이 호스트코드 [02] 에서는 생성한 WildTurkey 객체를 TurkeyAdapter로 한번 감싸서, 오리류(IDuck) 전용의 testDuck 메서드에 던지고 MallardDuck의 메서드인 quack() 과 fly() 메서드명을 사용하지만, WildTurkey의 gobble() 과 fly() 메서드를 실행하게 할 수 있습니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package { import flash.display.Sprite; public class Main extends Sprite { public function Main():void { var duck:MallardDuck = new MallardDuck(); var turkey:WildTurkey = new WildTurkey(); var turkeyAdapter:IDuck = new TurkeyAdapter( turkey ); trace( "n칠면조가 말함" ); turkey.gobble(); turkey.fly(); trace( "n오리가 말함" ); testDuck( duck ); trace( "n칠면조 어댑터가 말함" ); testDuck( turkeyAdapter ); } private function testDuck( $duck:IDuck ):void { $duck.quack(); $duck.fly(); } } } |

호스트코드의 실행 결과.
이 호스트 코드를 실행하면 왼쪽 trace문을 볼 수 있습니다.
참고로 testDuck( turkeyAdapter ); 에 오리로 감싼 칠면조를 인자로 던지지 않고 testDuck( turkey ); 칠면조를 직접 던지면 컴파일 에러가 발생합니다. 컴파일러의 입장에서는 testDuck( $duck:IDuck ); 메서드는 인자를 오리로 던지라는데 칠면조를 던졌으므로 type casting 에러가 발생하게 되는 것이죠.
Adapter Pattern Example 액션스크립트 코드 다운로드 (137)

이런 광경이 연상됩니다.
Blog under the Creative Commons Attribution-NoDerivs 3.0 License
5월 14th, 2009 on pm 7:40
짱인듯.
정말이지 실제로 공부한다는건 어려운건데 ^^;
화이팅입니다.
5월 14th, 2009 on pm 8:34
네 감사합니다.
코드를 만들면서 이해를 하게 되고, 이 포스트를 보는 다른 분들도 이해를 할 수 있도록 써야 하니까 설명을 달면서 한 번더 이해를 하게 되는것 같아요.
7월 8th, 2009 on pm 2:24
좋은 내용 감사합니다 ^.^
물오리의 탈을쓴..거위가 울고 나는군요 ㅋ
7월 8th, 2009 on pm 10:16
실제로 코드를 실행해 보면 재미있죠.