ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Adapter
    Java/디자인패턴 2020. 12. 21. 23:57

    바꿔서 재이용하기

     

    본 글은 java 언어로 배우는 디자인 패턴 입문 교적을 바탕으로 기재한 내용입니다.


    한번은 도쿄에 놀러간 적이 있었다. 숙소에서 집에서 쓰던 충전기 이외에 필요한 110V용 플러그 어댑터를 몇개씩 챙겨간 기억이 있다. (확실히 필요했다.)

     

    충전 단자 (110V) ---- 플러그 어댑터 ------ 핸드폰 충전기(220V)

     

    프로그램에서도 이미 제공되어 잇는 것을 그대로 사용할 수 없을 때, 필요한 형태로 교환하고 사용하는 일이 자주 있다. 

    '이미 제공되어 있는 것' 과 '필요한 것' 사이의 차이를 없애주는 디자인 패턴이 Adapter 패턴이다.

     

    Adapter 패턴은 Wrapper 패턴이라고 불리기도 한다 wrapper(감싸는 것)

     

    Adapter패턴은 다음과 같이 두 가지 종류가 있다.

    • 클래스에 의한 Adapter 패턴(상속을 사용한 Adapter 패턴)
    • 인스턴스에 의한 Adapter 패턴(위임을 사용한 Adapter 패턴)

     

    예제 프로그램(1) - 상속을 사용한 Adapter 패턴

    이미 제공되어 있는 클래스

    public class Banner {
        private String string;
    
        public Banner(String string) {
            this.string = string;
        }
    
        public void showWithParen() {
            System.out.println("(" + string + ")");
        }
    
        public void showWithAster() {
            System.out.println("*" + string + "*");
        }
    }

    충전단자(110V)

    showWithParen() : 현수막을 ( ) 로 묶어서 출력

    showWithAster() : 현수막을 * * 로 묶어서 출력

     

     

    필요로 하는 인터페이스

    public interface Print {
        public abstract void printWeak();
    
        public abstract void printStrong();
    }

    핸드폰 충전기(220V)

    printWeak() : 약하게 출력한다는 의미

    printString() : 강하게 출력한다는 의미

     

     

    차이를 없애주는 클래스

    public class PrintBanner extends Banner implements Print {
    
        public PrintBanner(String string) {
            super(string);
        }
    
        public void printWeak() {
            showWithParen();
        }
    
        public void printStrong() {
            showWithAster();
        }
    }

    플러그 어댑터

    이 클래스는 제공 되어 있는 Banner 클래스를 상속해서, 필요로 하는 Print 인터페이스를 구현한다. 

     

    showWithParen 메소드를 사용해서 printWeak을 구현하고

    showWithAster 메소드를 사용해서 printStrong을 구현한다.

     

    실행

    public class Main {
        public static void main(String[] args) {
            Print p = new PrintBanner("Hello");
            p.printWeak();
            p.printStrong();
        }
    }
    
    
    // (Hello)
    // *Hello*

     

     

    예제 프로그램(2) - 위임을 사용한 Adapter 패턴

    * 위임 : '누군가에게 맡긴다' Java에서 위임은 어떤 메소드의 실제 처리를 다른 인스턴스의 메소드에게 맡기는 것을 말한다.

     

    이미 제공되어 있는 클래스 (1) 과 동일

    public class Banner {
        private String string;
    
        public Banner(String string) {
            this.string = string;
        }
    
        public void showWithParen() {
            System.out.println("(" + string + ")");
        }
    
        public void showWithAster() {
            System.out.println("*" + string + "*");
        }
    }

     

    필요로 하는 클래스

    public abstract class Print {
        public abstract void printWeak();
    
        public abstract void printStrong();
    }
    

     

    차이를 없애주는 클래스

    public class PrintBanner extends Print {
        private Banner banner;
    
        public PrintBanner(String string) {
            this.banner = new Banner(string);
        }
    
        public void printWeak() {
            banner.showWithParen();
        }
    
        public void printStrong() {
            banner.showWithAster();
        }
    }
    

    java 에서는 2개의 클래스를 동시에 상속할 수 없기 때문에(단일상속) PrintBanner 클래스는 banner 필드에서 Banner 클래스의 인스턴스를 가진다. (이 인스턴스는 클래스의 생성자에서 생성한다)

     

    (1) 에서는 자신의 상위 클래스에서 상속한 showWithParen, showWithAster 메소드를 호출하고 있는 반면에

    (2) 에서는 필드를 경유해서(위임해서) showWithParen, showWithAster 메소드를 호출 하고 있다.

     

    메인 Class도 동일

     

    패턴의 등장인물

    * Target(대상) 의 역할
    지금 필요한 메소드를 결정한다 (220V충전기 역할)
    예제에서는 Print 인터페이스(상속), Print 클래스(위임)

    * Client(의뢰자) 의 역할
    Target 역할의 메소드를 사용해서 일을 한다. (핸드폰 역할)
    예제에서는 Main 클래스

    * Adaptee(개조되는 쪽) 의 역할
    이미 준비되어 있는 메소드를 가지고 있는 역할 (110V 전용 충전단자)
    예제에서는 Banner 클래스

    * Adapter의 역할
    (플러그 어댑터)
    Adaptee 역할의 메소드를 사용해서 어떻게든 Target 역할을 만족시키기 위함이 Adapter의 목적이다.
    예제에서는 PrintBanner 인터페이스, PrintBanner 클래스

     

    왜 Adapter 패턴?

    항상 처음부터 프로그래밍을 하는 경우만 있는 것이 아니다.

    이미 존재하고 있는 클래스를 이용하는 경우, 특히 그 클래스가 충분한 테스트를 받아 버그가 적고 사용 실적이 있는 경우 부품으로 재이용하고 싶을 때 사용할 수 잇다. 

     

    Adapter 패턴의 목적은 기존 소스를 수정하지 않고 목적한 인터페이스(API)에 맞추기 위함이다. 

    예를 들어 소프트웨어의 구버전과 신버전을 공존시키고 유지보수를 편히 하기 위해 신버전만 유지보수 하려고 할때

    신버전을 Adaptee역할로 하고, 구버전을 Target 역할로 지정하여 호환을 위한 Adapter역할의 클래스를 만들수 있다.

     

     

    관련패턴

    Bridge패턴 : adapter 패턴은 인터페이스(API)가 서로 다른 클래스를 연결하는 패턴이다. Bridge패턴은 기능의 계층과 구현의 계층을 연결시키는 패턴이다.

    Decorator 패턴 : adapter패턴은 인터페이스(API)의 차이를 조정하기 위한 패턴이다. Decorator패턴은 인터페이스(api)를 수정하지 않고 기능을 추가하는 패턴이다.

    'Java > 디자인패턴' 카테고리의 다른 글

    Prototype  (0) 2021.01.01
    Singleton  (0) 2020.12.31
    Factory Method  (0) 2020.12.27
    Template Method  (0) 2020.12.22
    Iterator  (0) 2020.12.20
Designed by Tistory.