Effective Java : 아이템24. 완벽공략 - 어댑터 패턴

    들어가기 전

    이 글은 인프런 백기선님의 이펙티브 자바 강의를 복습하며 작성한 글입니다. 


    이 글의 요약 

    • 어댑터 패턴은 클라이언트가 요청하는 타입과 이미 구현된 클래스가 호환되지 않을 때, 중간에 Adapter 클래스를 하나 생성해서 서로 호환될 수 있도록 해준다.
    • Adapter 클래스는 클라이언트가 요청하는 타입(인터페이스 / 클래스)를 상속/구현한다. 따라서 호환 가능해진다. 
    • Adapter 클래스는 비정적 멤버 클래스로 선언해서 사용하면 좀 더 응집도 있게 코드를 작성할 수 있다. 

    완벽 공략 39. 어댑터 패턴 

    어댑터 패턴의 목적은 다음과 같다. 

    • 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴

    예를 들어 클라이언트가 바라는 타겟은 220v를 사용하고 있는데, 우리가 이미 구현한 클래스는 110v를 사용하고 있다. 이 클래스를 클라이언트에서 그대로 사용할 수 있도록 110v를 220v로 변환시켜주는 작업을 해야한다. 이 작업을 '어댑터 패턴'을 통해서 할 수 있다. 

     

    코드로 보기

    아래 코드를 살펴보자. 아래 코드의 각 클래스 / 인터페이스가 어디에 해당되는지를 살펴보자. 

    • Iterator : Target 인터페이스. 클라이언트가 필요로 하는 인스턴스다.
    • MySet : Adaptee. 내가 구현한 코드다. 
    • MyIterator : Adapater다. 정적 내부 클래스로 사용됨. 
    public class MySet<E> extends AbstractSet<E> {
        @Override
        public Iterator<E> iterator() {
            // MySet은 Iterator가 없다. --> 사용자는 Iterator 타입을 사용하고 싶어함.
            // Adapter 패턴을 이용해서 처리할 수 있음.
            return new MyIterator();
        }
    
        @Override
        public int size() {
            return 0;
        }
    
        // 어댑터 역할
        private class MyIterator implements Iterator<E> {
            @Override
            public boolean hasNext() {
                return false;
            }
    
            @Override
            public E next() {
                return null;
            }
        }
    }

    내가 MySet이라는 클래스를 이미 다 구현한 상황이라고 가정해보자. 그런데 이 때, Client는 MySet을 요청했을 때 Iterator 타입을 요구한다. 하지만 MySet은 Iterator 타입이 구현되어 있지 않아서 반환할 수 없는 상황이다. 즉, MySet이 구현한 타입과 클라이언트가 요청하는 타입이 맞지 않기 때문에 중간에 Adapter 클래스가 필요한 것이다. 

    Adapter 클래스의 역할을 하는 것은 MyIterator다. MyIterator는 클라이언트가 원하는 Iterator 인터페이스를 구현한다. 따라서 MyIterator는 Iterator와 호환가능해진다. 위 코드 흐름을 정리하면 다음과 같다. 

    클라이언트는 Iterator 타입을 필요로 한다. 하지만 MySet은 Iterator 타입이 존재하지 않아서 클라이언트가 사용할 수 없었다. 클라이언트가 MySet을 사용할 수 있도록 MySet 내부에 정적 멤버 클래스로 Adapter 역할을 할 MyIterator를 생성햇다. MyIterator는 Iterator 인터페이스를 구현했기 때문에 Iterator 타입과 호환가능해져서, 어댑터로서의 역할을 할 수 있게 되었다.


    자바에서 쓰이는 것 

    자바에서도 내부적으로 비정적 멤버 클래스 형태로 Adapter 패턴이 사용되고 있다.

    • HashMap은 Set 형태로도 사용되고 싶어한다. 왜냐하면 클라이언트가 그 타입을 요청하기 때문이다. 하지만 HashMap은 KeySet을 전달해줄 수 없다. 구현이 되어 있지 않기 때문이다. 
    • HashMap은 비정적 멤버 클래스로 KeySet을 가진다. KeySet은 AbstractSet을 구현한다. 따라서 KeySet은 Set과 호환될 수 있는 Adapter로 동작한다. 
    • 따라서 HashMap은 Set으로 동작하기 위해서 비정적 멤버 클래스로 KeySet을 선언하고, KeySet을 어댑터로 이용한다. 

     

     


    참조

    댓글

    Designed by JB FACTORY