취업과 기본기 튼튼/빽 투더 기본기
[디자인 패턴 6편] 구조 패턴, 어댑터(Adapter)
흠시
2020. 2. 18. 18:22
1. 개념
어댑터 패턴은 서로 다른 인터페이스를 가진 두 클래스를
어댑터 클래스로 인터페이스를 통일 시켜 사용하는 방법이다.
1.1. 장점
- 기존 클라이언트 단의 코드 수정 최소화.
- 클라이언트는 연동부분을 몰라도, 새로운 코드의 기능을 일관되게 사용가능.
1.2. 단점
- 어댑터 클래스에서 통일 시켜주는 부분을 하나씩 구현해야 함.
1.3. 활용 상황
- 기존의 코드에 새로운 코드(써드파티 라이브러리 등)을 연동하여 사용하고 싶은데, 두 코드의 인터페이스가 달라, 이를 하나로 통일하여 사용하고 싶을 때.
- 아래 예의 경우, 기존의 클라이언트 단 코드에 맞춰 통일함.
2. 구조
3. 코드
3.1. 적용 전/후 모습
먼저 사전에 mp3
포맷만 지원하는 AudioPlayer
가 정의되어있고,
메인에서는 다음과 같이 사용했다고 해보자.
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
}
}
그런데, 앞으로는 mp3
뿐만 아니라 mp4
와 vlc
도 지원해야 한다는 요구사항이 들어왔다.
이 포맷들을 실행시킬 수 있는 Mp4Player
와 VlcPlayer
가 이미 구현되어 있다고 한다.
이미 구현되어 있는 두 개의 객체를 어떻게 하면 연동시켜서 사용할 수 있을까?
어댑터 패턴을 사용하면 클라이언트단에서는 단순히 다음만 추가해주면 된다.
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
}
}
AudioPlayer
의 쓰이는 모습이 전혀 달라진게 없이도, 추가 포맷을 지원하고 있다.
내부적으로 어떻게 되어있나 하나씩 살펴보자.
3.2. 적용 과정
먼저 기존의 AudioPlayer
의 코드는 다음과 같았다.
public interface MediaPlayer {
public void play(String audioType, String fileName);
}
public class AudioPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("mp3"))
System.out.println("Playing mp3 file. Name: " + fileName);
}
}
현재로썬 그냥 mp3
만 지원되고 있다.
한편, 우리가 가져다 쓰려는 VlcPlayer
와 Mp4Player
의 모습은 다음과 같다.
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}
@Override
public void playMp4(String fileName) {
}
}
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
//do nothing
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}
vlc
와 mp3
확장자의 추가 지원을 위해 AudioPlayer
에 다음을 추가한다.
public class AudioPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: " + fileName);
}
// 'vlc' 나 'mp4' 포맷은 MediaAdapter 로 처리한다.
else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
}
}
MediaAdapter
가 등장했다. 이는 다음과 같이 정의한다.
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType){
// 생성 시, vlc 인지 mp4 인지 구분.
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
}else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
// play 호출 시, 구체적인 각 플레이어의 메쏘드를 호출.
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}
자 이제 클라이언트 단을 다시 보자.
다음과 같이 잘 작동하게 된다.
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc