본문 바로가기

기타/객체지향의 탄생(2013)

객체지향의 탄생- Adapter pattern

 

  1. 어뎁터 패턴(Adapter)

1. 누구에게나 정이 가고 애착이 가고 꼭 필요한 물건이 있다. 여자라면 가방이나, 집의 소품, 남자라면 자동차와 카메라, 전자 제품이 있을 것이다. 나에게 가장 소중한 물건은 '아이폰' 이다.

 

나는 옛날부터 전화기, MP3, 게임기, 카메라, 동영상 플레이어의 휴대용 기기가 통합된 단 하나의 기기를 갖기를 손꼽아 기다렸다.

 

나에게 아이폰은 나의 희망사항에 가장 근접한 기술력과 모양을 갖춘 꿈의 기기 였다. 아이폰은 내가 심심하지 않도록 언제나 옆에서 함께하는 친구와 같았다. 그래서 나는 아이폰을 좋아한다.

심지어는 아이폰과 잡스를 동경해 아이폰 개발자로 전향했다.

 

2. 몇년 후 나는 아이폰 개발자이기도 해서 컴퓨터는 맥미니를 쓰고, 뉴 아이패드를 쓰고, 아이폰을 쓰고 있다. 그뒤 출시된 아이패드 미니는 크기와 무게가 내가 원하는 모양이었다.

 

우연히 아이패드 미니를 손에 넣게 되었다. 아이패드 미니를 쓰는데 한가지 당황스러운 점이 생겼다. USB 케이블 포트가 맞지 않는 것이다.

 

[아이패드 미니를 샀는데 기존 어뎁터로는 맞지 않는다.]

 

해결 방법은 아이패드 미니에 맞는 라이트닝 커넥터를 쓰는 방법이 하나 있다. 만약 사용자가 기존 USB를 기준으로 아이패드 미니에 연결하고 싶다면 어뎁터를 구입하여 연결하는 방법도 있다.

 

[어뎁터가 필요하다. 그림]

 

이렇게 어뎁터는 서로 맞지 않는 인터페이스를 연결해주는 역할을 한다. 객체지향에서도 서로 맞지 않는 인터페이스/메소드를 연결해주는 어뎁터 클래스를 만들 수 있다.

 

[아이폰/아이패드 어뎁터 클래스]

 

package adapter;

 

public abstract class iphoneOldDeviceFeature {

 

    public abstract void iphoneFunctions();

    

    public abstract void usbPin30();

}

[옛날 아이폰 추상 클래스 생성]

 

package adapter;

 

public class iphone4S extends iphoneOldDeviceFeature {

 

    @Override

    public void iphoneFunctions() {

        System.out.println("아이폰4S 특징");

    }

 

    @Override

    public void usbPin30() {

        System.out.println("아이폰4S 30핀 커넥터 연결");

    }

} 

[아이폰4S 클래스]

 

package adapter;

 

public class NewiPad extends iphoneOldDeviceFeature {

 

    @Override

    public void iphoneFunctions() {

        System.out.println("뉴아이패드 특징");

    }

 

    @Override

    public void usbPin30() {

        System.out.println("뉴아이패드 30핀 커넥터 연결");

    }

 

} 

[뉴아이패드 클래스]

 

package adapter;

 

public abstract class iphoneNewDeviceFeature {

    

    public abstract void iphoneFunctions();

    

    public abstract void lightningPin();

} 

[새로운 스펙으로 출시된 아이폰/아이패드 추상 클래스]

 

package adapter;

 

public class iPadMini extends iphoneNewDeviceFeature {

 

    @Override

    public void iphoneFunctions() {

        System.out.println("아이패드 미니 특징");

    }

 

    @Override

    public void lightningPin() {

        System.out.println("아이패드 미니의 라이트닝 커넥터 연결");

    }

}

[아이패드 미니]

 

package adapter;

 

public abstract class USBPin30Feature {

    

    public abstract void conntector();

} 

[USBPin30 추상 클래스]

 

package adapter;

 

public class USBPin30 extends USBPin30Feature {

    iphoneOldDeviceFeature oldIphone;

    

    public USBPin30(iphoneOldDeviceFeature iPhoneNew) {

        this.oldIphone = iPhoneNew;

    }

    

    @Override

    public void conntector() {

        oldIphone.usbPin30();

    }

} 

[USB 30핀 클래스]

 

package adapter;

 

public class USBPin30Adapter extends USBPin30Feature {

    iphoneNewDeviceFeature iPhoneNew;

    

    public USBPin30Adapter(iphoneNewDeviceFeature iPhoneNew) {

        this.iPhoneNew = iPhoneNew;

    }

    

    @Override

    public void conntector() {

        iPhoneNew.lightningPin();

    }

} 

[USBPin30 어뎁터 클래스, New 아이폰 스펙을 가진 클래스로 연결한다.]

 

package adapter;

 

public class Main {

    

    public static void main(String[] args) {

        // 아이폰4S, 뉴아이패드에 30핀 커넥터 연결

        iphoneOldDeviceFeature iphone4s = new iphone4S();

        iphoneOldDeviceFeature newiPad = new NewiPad();

        

        USBPin30Feature usbPin30 = new USBPin30(iphone4s);

        USBPin30Feature usbPin30_2 = new USBPin30(newiPad);

        

        usbPin30.conntector();

        usbPin30_2.conntector();

        

        // 아이패드 미니에 USB30Pin<->Lightning 어뎁터를 통한 라이트닝 커넥터 연결

        iphoneNewDeviceFeature iPadMini = new iPadMini();

        USBPin30Feature usbPinLightniningAdapter = new USBPin30Adapter(iPadMini);

        usbPinLightniningAdapter.conntector();

    }

}

 

아이폰4S 30핀 커넥터 연결

뉴아이패드 30핀 커넥터 연결

아이패드 미니의 라이트닝 커넥터 연결

[실행 결과, 아이패드 미니의 라이트닝 단자로 연결한다.]

 

사용자는(Main 클래스) USBPin30Feature를 통해 아이폰 옛날 기기(iphoneOldDeviceFunction)

에 conntector() 메소드를 이용하여 USB를 연결, 충전도 하고 아이튠즈를 통해 기기에 접근한다.

 

만약 사용자가 2012년 이후 아이폰 최신 기기에 접근하고 싶을때, 현재 USBPin30Feature를 상속받는

USB 커넥터만 사용한다면 최신 기기에 접근할수 있는 방법이 없다.

 

구 기기 접근 메소드는 oldIphone.usbPin30() 인데, 최신 기기 접근 메소드는 iPhoneNew.lightningPin()

으로 접근해야 하기 때문에 접근할수 없다.

 

그러나 USBPin30Feature의 특징을 상속받으면서 iPhoneNewDeviceFeature에 의존하는 새로운 어뎁터

클래스를 만들면 현실의 USB30Pin<->LigntningPin 어뎁터와 같은 역할을 수행한다.

 

3. 어뎁터 패턴을 구현하기 위해서는 전형적인 구성/스트라테지 패턴으로 객체 패밀리를 구성하여 인터페이스를 상속받는 어뎁터 클래스를 만들고 이 어뎁터 클래스와 목표 클래스를 이어주는 식으로 구성되어 있다.

 

또는 이미 전형적인 구성/스트라테지 패턴으로 구성된 객체 패밀리에서 다른 클래스를 이어주어야 된다면 새로운 어뎁터 클래스를 하나 상속하여 만들고 목표클래스를 이어주면 된다.

 

어뎁터 패턴은 이미 결정된 인터페이스끼리 연결되어 작동중인 어플리케이션에서 호환되지 않는 인터페이스를 가진 클래스를 쓰기 위해, 호환되는 인터페이스와 호환되지 않는 인터페이스를 맞춰준다. 그래서 호환되지 않는 인터페이스도 사용할수 있게 해주는 패턴이다.

 

[어뎁터 패턴]

 

 

덧 ) 이 객체지향의 탄생 원고는 제가 책으로 내려다가 일단 잘 안되었는데요. 이유는 비문이 많다. 단락내 주제가 중복된다. 어떤 상황 설명을 과장한다.등 입니다. 그래도 원고를 일단 블로그에 몽땅 풀어보고 언젠가 제대로 교정해서 다시 도전할 생각입니다. 이점을 감안해서 읽고 객체지향을 이해하는데 도움이 되셨으면 좋겠습니다. 의견도 주셨으면 좋겠습니다. 원고 조금만 교정하면 괜찮을것 같은 출판사 관계자분의 피드백도 환영합니다. 매주 월요일 발행 예정입니다.