학습일지/Language
[Design Pattern] Adapter
inspirit941
2020. 12. 18. 08:17
반응형
Adapter Pattern
한 클래스의 인터페이스를, 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환하는 역할.
인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스를 연결하는 역할.
- 이미 제공되어 있는 것 / 필요한 것 사이의 차이를 없앤다고 보면 된다
- Wrapper 패턴이라고도 불림. 다른 용도로 사용할 수 있도록 변경해주는 개념
두 가지 종류가 있다.
- Class 기반 Adapter (상속을 사용한 방법)
- Instance 기반 Adapter (위임을 사용한 방법)
기존의 클래스를 개조해서 필요한 클래스를 생성하는 방법.
일반적으로 기존의 클래스 == "잘 만들어졌고, 버그가 발생하지 않는다는 걸 오랜 시간 사용하며 증명한 코드". 이 클래스를 더 많은 곳에서 다양한 방식으로 사용하기 위해 고안한 게 Adapter 패턴.
- 이미 있는 클래스를 사용하므로, 필요한 메소드를 빠르게 생성할 수 있음
- 버그가 발생해도 기존 클래스에는 버그가 없을 가능성이 크므로, Adapter 클래스 위주로 디버깅하면 된다.
이미 만들어진 클래스를 새 인터페이스에 맞게 개조할 때...
- Adapter를 사용하지 않고 기존 클래스를 수정할 경우: 동작 테스트가 이미 끝난, 통과했던 테스트들을 전부 다시 실행해봐야 함.
- Adpater를 사용할 경우: 기존 클래스는 그대로 두고 원하는 인터페이스만 맞추는 형태이므로, 기존 클래스의 인터페이스만 제대로 안다면 생성해 사용할 수 있음.
public interface APlayer {
void play(String fileName);
void stop();
}
public class APlayerImpl implements APlayer {
@Override
public void play(String fileName) {
System.out.println("(A) " + fileName);
}
@Override
public void stop() {
}
}
public interface BPlayer {
void playFile(String fileName);
void StopFile();
}
public class BPlayerImpl implements BPlayer {
@Override
public void play(String fileName) {
System.out.println("(B) " + fileName);
}
@Override
public void stop() {
}
}
public class TestAdapterPattern {
public static void main(String[] args) {
APlayer aplayer = new APlayerImpl();
player.play("test.mp3");
// 계약기간 만료로 이전까지의 APlayerImpl는 사용할 수 없다고 가정.
// 새로 도입된 BPlayer방식을 사용해야 할 경우
// APlayer로 잘 작동하던 코드를 최대한 변경없이 사용하고자 함
aplayer = new BtoAAdapter(new BPlayerImpl());
aplayer.play("test2.mp3");
// 모든 코드가 Aplayer 인터페이스에 맞춰져 있으므로
// 전체 코드를 BPlayer로 변경하는 대신, BPlayer로 변환하는 어댑터 클래스만 제대로 생성하면 된다.
}
}
// Adapter
// 기존 코드에서 수정해야 할 부분을 Adapter에서 적용함.
// 기존에 잘 쓰이던 클래스이므로, 버그 발생 시 Adapter 부분만 확인하면 된다.
public class BtoAAdapter implements APlayer {
private BPlayer media;
public BtoAAdapter(BPlayer media) { this.media = media; }
@Override
public void play(String fileName) {
System.out.println("Using Adapter : ");
media.playFile(fileName);
}
@Override
public void stop(){}
}
만약 BPlayer가 Abstract Class라면
public abstract class BPlayer {
public abstract void playFile(String fileName);
public abstract void StopFile();
}
public class BPlayerImpl extends BPlayer {
@Override
public void play(String fileName) {
System.out.println("(B) " + fileName);
}
@Override
public void stop() {
}
}
public class BtoAAdapter extends BPlayerImpl implements APlayer {
private BPlayer media;
public BtoAAdapter(BPlayer media) { this.media = media; }
@Override
public void play(String fileName) {
System.out.println("Using Adapter : ");
media.playFile(fileName);
}
@Override
public void stop(){}
}
반응형