在软件开发过程中,我们经常会遇到这样的情况:需要使用一个已经存在的类,但它的接口并不符合我们的需求。适配器模式(Adapter Pattern)就是为了解决这一问题而设计的。它可以将一个类的接口转换成客户希望的另一个接口,从而使原本由于接口不兼容而无法一起工作的类可以协同工作。
本文将详细解析适配器模式的基本原理、实现方法、应用场景及其优缺点,并通过具体示例演示如何在实际项目中应用适配器模式。
适配器模式属于结构型设计模式,它通过引入一个适配器类,将一个类的接口转换为客户希望的另一个接口。适配器模式主要包括以下几种类型:
类适配器模式使用多继承来实现适配器,适配器继承了被适配的类,同时实现目标接口。这种方式适用于适配器和被适配类存在父子关系的情况,但由于 Java 不支持多继承,因此在 Java 中类适配器模式较少使用。
对象适配器模式使用组合来实现适配器,适配器包含被适配的对象,并通过调用被适配对象的方法来实现目标接口的方法。这种方式更加灵活,也更常用。
下面我们通过一个具体的示例来演示适配器模式的实现。
假设我们有一个 MediaPlayer
接口和一个 AdvancedMediaPlayer
接口,前者可以播放 mp3 格式的音频文件,后者可以播放 vlc 和 mp4 格式的音频文件。我们希望通过适配器模式,使 MediaPlayer
接口也能播放 vlc 和 mp4 格式的音频文件。
// MediaPlayer 接口
public interface MediaPlayer {
void play(String audioType, String fileName);
}
// AdvancedMediaPlayer 接口
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
// VlcPlayer 类实现 AdvancedMediaPlayer 接口
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) {
// 什么也不做
}
}
// Mp4Player 类实现 AdvancedMediaPlayer 接口
public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// 什么也不做
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: " + fileName);
}
}
// MediaAdapter 类实现 MediaPlayer 接口
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
// AudioPlayer 类实现 MediaPlayer 接口
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// 播放 mp3 音乐文件的内置支持
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file. Name: " + fileName);
}
// mediaAdapter 提供了播放其他文件格式的支持
else 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 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.play("avi", "mind me.avi");
}
}
运行结果:
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported
适配器模式适用于以下几种场景:
适配器模式是一种重要的结构型设计模式,通过引入适配器类,将一个类的接口转换成客户希望的另一个接口,从而使不兼容的类可以协同工作。本文详细介绍了适配器模式的基本原理、实现方法、应用场景及其优缺点,并通过具体示例演示了适配器模式的实际应用。