Design Pattern/구조 디자인 패턴
어댑터 패턴(Adapter Pattern)이란?
슝슝이입니다
2024. 4. 14. 14:55
반응형
어댑터 패턴은 서로 호환되지 않는 인터페이스를 가진 클래스들이 함께 작동할 수 있도록 하는 구조적 디자인 패턴입니다. 이 패턴은 기존 시스템과 새 시스템, 라이브러리 또는 애플리케이션 간의 인터페이스 차이를 극복하기 위해 중간에 어댑터 클래스를 사용하여 호환성 문제를 해결합니다.
1. 어댑터 패턴은 주로 어디에 쓰이나?
어댑터 패턴은 주로 다음과 같은 상황에서 사용됩니다:
- 기존 시스템과 새 시스템 간의 통합: 다른 인터페이스를 가진 두 시스템이 서로 통신해야 할 때.
- 라이브러리 교체: 기존 코드를 변경하지 않고 새로운 라이브러리 또는 도구를 기존 시스템에 통합할 때.
- 플랫폼 독립적인 코드 작성: 다양한 플랫폼에서 작동하는 코드를 개발할 때.
2. Java와 Go로 어댑터 패턴을 구현할 때의 차이점
- Java: Java에서는 클래스 상속 또는 인터페이스를 사용하여 어댑터 패턴을 구현할 수 있습니다. 일반적으로 인터페이스를 통한 구현이 선호됩니다.
- Go: Go는 상속을 지원하지 않으며, 인터페이스만을 사용하여 어댑터 패턴을 구현합니다. 구조체와 인터페이스를 함께 사용하여 동일한 기능을 제공합니다.
3. 어댑터 패턴 예시
Java 예시:
// Target Interface
interface MediaPlayer {
void play(String audioType, String fileName);
}
// Adaptee
class AdvancedMediaPlayer {
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: " + fileName);
}
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: " + fileName);
}
}
// Adapter
class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new AdvancedMediaPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new AdvancedMediaPlayer();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
// Client
class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}
public class Main {
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.play("avi", "mind me.avi");
}
}
- 인터페이스 정의:
- MediaPlayer 인터페이스는 play 메소드를 정의합니다. 이 메소드는 음악 파일의 타입과 파일 이름을 매개변수로 받습니다.
- Adaptee 클래스:
- AdvancedMediaPlayer 클래스는 VLC와 MP4 파일을 재생하는 기능을 가집니다. 이 클래스는 playVlc와 playMp4 메소드를 포함하여 각각의 파일 타입에 대한 재생 로직을 구현합니다.
- Adapter 클래스:
- MediaAdapter 클래스는 MediaPlayer 인터페이스를 구현하며, AdvancedMediaPlayer 객체를 사용하여 다양한 파일 형식을 재생합니다. 이 어댑터는 audioType에 따라 적절한 메소드를 호출하여 파일을 재생합니다.
- Client 클래스:
- AudioPlayer 클래스는 기본적으로 MediaPlayer 인터페이스를 구현합니다. 특정 파일 타입을 재생할 때 MediaAdapter를 사용하여 필요한 형식에 맞게 파일을 재생할 수 있습니다. 지원하지 않는 파일 형식에 대해선 오류 메시지를 출력합니다.
Go 예시:
package main
import "fmt"
// Target interface
type MediaPlayer interface {
Play(audioType, fileName string)
}
// Adaptee
type AdvancedMediaPlayer struct{}
func (amp *AdvancedMediaPlayer) PlayVLC(fileName string) {
fmt.Println("Playing vlc file. Name:", fileName)
}
func (amp *AdvancedMediaPlayer) PlayMP4(fileName string) {
fmt.Println("Playing mp4 file. Name:", fileName)
}
// Adapter
type MediaAdapter struct {
advancedMusicPlayer *AdvancedMediaPlayer
}
func NewMediaAdapter(audioType string) *MediaAdapter {
adapter := &MediaAdapter{
advancedMusicPlayer: &AdvancedMediaPlayer{},
}
return adapter
}
func (adapter *MediaAdapter) Play(audioType, fileName string) {
if audioType == "vlc" {
adapter.advancedMusicPlayer.PlayVLC(fileName)
} else if audioType == "mp4" {
adapter.advancedMusicPlayer.PlayMP4(fileName)
}
}
// Client
type AudioPlayer struct{}
func (player *AudioPlayer) Play(audioType, fileName string) {
if audioType == "vlc" || audioType == "mp4" {
adapter := NewMediaAdapter(audioType)
adapter.Play(audioType, fileName)
} else {
fmt.Println("Invalid media. ", audioType, " format not supported")
}
}
func main() {
player := &AudioPlayer{}
player.Play("mp4", "myVideo.mp4")
player.Play("vlc", "myMusic.vlc")
}
- 인터페이스 정의:
- Go에서는 MediaPlayer 인터페이스를 정의하여 Play 메소드를 포함합니다. 이 메소드는 오디오 타입과 파일 이름을 매개변수로 받습니다.
- Adaptee 구조체:
- AdvancedMediaPlayer 구조체는 PlayVLC와 PlayMP4 메소드를 통해 VLC와 MP4 파일 재생을 지원합니다.
- Adapter 구조체:
- MediaAdapter 구조체는 MediaPlayer 인터페이스를 구현합니다. 이 구조체는 AdvancedMediaPlayer를 포함하며, 생성자 NewMediaAdapter를 통해 초기화됩니다. Play 메소드를 통해 파일 타입에 맞는 재생 함수를 호출합니다.
- Client 구조체:
- AudioPlayer 구조체는 MediaPlayer 인터페이스를 구현하고, 지원하는 파일 형식을 확인하여 MediaAdapter를 사용해 파일을 재생합니다. 지원하지 않는 형식일 경우 오류 메시지를 출력합니다.
이러한 방식으로, Java와 Go 둘 다에서 어댑터 패턴을 활용하여 다양한 오디오 파일 타입을 처리하는 능력을 소프트웨어에 통합할 수 있습니다. 어댑터는 기존 코드와 새로운 코드 사이에서 호환성을 제공하는 중간자 역할을 수행하여 코드의 재사용성과 유지보수성을 높여줍니다.
4. 어댑터 패턴의 장단점
장점:
- 기존 코드 변경 없이 새로운 인터페이스를 소프트웨어에 통합할 수 있습니다.
- 기존 클래스가 예상하지 못한 환경에서 재사용될 수 있습니다.
단점:
- 전체 시스템의 복잡성이 증가할 수 있습니다.
- 때때로 많은 추가 객체의 생성이 필요하여, 시스템의 오버헤드가 늘어날 수 있습니다.
반응형