Effective Java : 아이템24. 완벽공략 - 어댑터 패턴
- 프로그래밍 언어/JAVA
- 2023. 4. 15.
들어가기 전
이 글은 인프런 백기선님의 이펙티브 자바 강의를 복습하며 작성한 글입니다.
이 글의 요약
- 어댑터 패턴은 클라이언트가 요청하는 타입과 이미 구현된 클래스가 호환되지 않을 때, 중간에 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을 어댑터로 이용한다.
참조
'프로그래밍 언어 > JAVA' 카테고리의 다른 글
Effective Java : 아이템26. 완벽공략 (GenericRepository) (0) | 2023.04.16 |
---|---|
Effective Java : 아이템26. 로 타입은 사용하지 마라 (제네릭) (0) | 2023.04.15 |
Effective Java : 아이템24. 멤버 클래스는 되도록 static으로 만들라. (0) | 2023.04.15 |
Effective Java : 아이템23. 태그 달린 클래스보다는 클래스 계층 구조를 활용하라. (0) | 2023.04.12 |
Effective Java : 아이템22. 인터페이스는 타입을 정의하는 용도로만 사용하라. (0) | 2023.04.12 |