일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 30 |
- 패스트캠퍼스
- 데이터베이스
- 디자인패턴
- 국비
- 자바
- javabasic
- 직장인자기계발
- linux
- java기초
- ncs
- DesignPattern
- 디자인
- 패스트캠퍼스후기
- 패캠챌린지
- String
- 자바기본
- 한번에끝내는JavaSpring웹개발마스터초격차패키지Online강의
- 한번에끝내는JavaSpring웹개발마스터초격차패키지Online
- Spring
- 자바예제
- js
- 웹
- 스프링
- 자바연습문제
- 직장인인강
- DB
- 자바기초
- 재택근무
- 리눅스
- java
- Today
- Total
FIF's 코딩팩토리
어댑터 패턴(Adapter Pattern) 정리 본문
어댑터 패턴(Adapter Pattern) 정의한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다. 어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있다. |
호환되지 않는 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있다.
이렇게 함으로써 클라이언트와 구현된 인터페이스를 분리시킬 수 있으며, 향후 인터페이스가 바뀌더라도 그 변경 내역은 어댑터에 캡슐화 되기 때문에 클라이언트는 바뀔 필요가 없어진다.
어댑터 패턴 클래스 다이어 그램
전기 콘센트를 보면 이해가 쉽다.
한국의 표준 플러그를 일본 전원 소켓에 바로 끼우지 못해 동그란 모양을 일자로 바꿔주는 어댑터를 끼워야 한다.
이와 같이 어댑터는 소켓의 인터페이스를 플러그에서 필요로 하는 인터페이스로 바꿔준다고 할 수 있다.
객체지향에서 어댑터는 일상 생활과 동일하게 어떤 인터페이스를 클라이언트에서 요구하는 형태의 인터페이스에 적응시켜주는 역할을 한다.
Duck.interface
public interface Duck {
public void quack();
public void fly();
}
MallardDuck.java
public class MallardDuck implements Duck {
@Override
public void quack() {
System.out.println("Quack");
}
@Override
public void fly() {
System.out.println("I'm flying");
}
}
Turkey.interface
public interface Turkey {
public void gobble();
public void fly();
}
WildTurkey.java
public class WildTurkey implements Turkey{
@Override
public void gobble() {
System.out.println("Gobble gobble");
}
@Override
public void fly() {
System.out.println("I'm flying a short distance");
}
}
Duck객체가 모자라서 Turkey객체를 대신 사용해야 하는 상황이라 가정하자.
인터페이스가 다르기 때문에 Turkey객체를 바로 사용할 수 없다.
어댑터 만들기
TurkeyAdapter.java
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack(){
turkey.gobble();
}
@Override
public void fly() {
turkey.fly();
}
}
DuckTestDrive
public class DuckTestDrive {
public static void main(String[] args) {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("The turkey says...");
turkey.gobble();
turkey.fly();
System.out.println("The Duck says...");
testDuck(duck);
System.out.println("The TurkeyAdapter says...");
testDuck(turkeyAdapter);
}
public static void testDuck(Duck duck){
duck.quack();
duck.fly();
}
}
클라이언트 -> request() -> 어댑터 -> translatedRequest() -> 어댑터
클라이언트는 타겟 인터페이스에 맞게 구현, 어댑터는 타겟 인터페이스를 구현하며, 어댑터 인터페이스가 들어있다.
어댑터에는 두종류가 있다.
1. 객체 어댑터
2. 클래스 어댑터
클래스 어댑터 패턴을 쓰려면 다중 상속이 필요한데, 자바는 기본적으로 다중 상속이 불가능.
두 어댑터의 클래스 다이어그램을 보면 이해가 수월하다.
클래스 어댑터
객체 어댑터
두 클래스 다이어그램에서 Target은 오리, Adapter는 칠면조라고 볼 수 있다.
클래스 어댑터에서는 어댑터를 만들 때 타겟과 어댑터 모두 서브 클래스로 만들고, 객체 어댑터에서는 구성을 통해 어댑터에 요청을 전달한다는 점을 제외하면 별다른 차이가 없다.
구식 Enumeration.
Enumeration을 리턴하는 element() 메소드가 구현되어 있었던 초기 컬렉션 형식(Vector, Stack, Hashtable 등) Enumeration 인터페이스를 이용하면 컬렉션 내에서 각 항목이 관리되는 방식에는 신경 쓸 필요 없이 컬렉션의 모든 항목에 접근 가능하다.
신형 Iterator
SUN에서 새로운 컬렉션 클래스를 출시하면서 Enumeration과 마찬가지로 컬렉션에 있는 일련의 항목들에 접근할 수 있게 해주면서 항목을 제거할 수 있게 해주는 Iterator라는 인터페이스를 이용하기 시작했다.
개발을 하다보면, Enumerator 인터페이스를 사용하는(구형 코드를 사용하는) 경우가 종종 있지만, 새로 만드는 코드에는 Iterator를 사용하는게 좋다.
이런 경우 어댑터 패턴을 적용하면 좋다.
public class EnumerationIterator implements Iterator{
Enumeration enumeration;
public EnumerationIterator(Enumeration enumeration) {
this.enumeration= enumeration;
}
@Override
public boolean hasNext(){
return enumeration.hasMoreElements();
}
@Override
public Object next() {
return enumeration.nextElement();
}
@Override
public void remove() {
throw new UnsupportedOperationException(); //예외 던짐 UnsupportedOperationException 지원
}
}
Enumeration에선 remove()에 해당하는 기능을 제공하지 않는다.(읽기전용 인터페이스다.)
어댑터 차원에서 완벽하게 작동하는 remove() 메소드를 구현할 방법은 없다.
그나마 가장 좋은 방법으로 예외를 던지는 방법인데, Iterator 인터페이스를 디자인한 사람들은 이런 필요성을 미리 예견하고 remove() 메소드를 구현할 때 UnsupportedOperation을 지원하도록 만들었다.
이런 경우는 어댑터가 완벽하게 적용될 수 없는 경우라고 할 수 있다.
하지만 클라이언트에서 충분히 주의를 기울이고 어댑터 문서를 잘 만들어 두면 상당히 쓸만한 해결책이 될 수 있다.
'Back-End > Design Pattern(디자인 패턴)' 카테고리의 다른 글
컴포지트 패턴(Composite Pattern) 정리 (0) | 2019.06.10 |
---|---|
퍼사드 패턴(Facade Pattern) 정리 (0) | 2019.06.10 |
이터레이터 패턴(Iterator Pattern) 정리 (0) | 2019.06.07 |
템플릿 메소드 패턴(Template Method Pattern) 정리 (0) | 2019.06.05 |
싱글톤 패턴(Singleton Pattern) 정리 (0) | 2019.06.05 |