1、适配器模式概念
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。比如电脑想要读取到SD卡的内容,那么必须要借助读卡器来实现,这个读卡器就是连接SD卡和电脑的桥梁了。
2、适配器模式的特点
- 结合了两个独立接口的功能。
- 有个单一的类,该类加入独立或不兼容的接口功能。
3、关于适配器模式
- 目的:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 解决问题:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
- 使用时机:
(1)系统需要使用现有的类,而此类的接口不符合系统的需要。
(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
(3)通过接口转换,将一个类插入另一个类系中。 - 保证模式:继承或依赖。
- 关键:适配器继承或依赖已有的对象,实现想要的目标接口。
4、优缺点
优点:
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度。
- 灵活性好。
缺点:
- 过多地使用适配器,会让系统非常零乱。如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
- 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
5、使用场景
有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
注意:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。
6、适配器模式的实现
现在有一个MediaPlayer接口和一个实现了MediaPlayer接口的实体类AudioPlayer。默认情况下,AudioPlayer可以播放mp3格式的音频文件。还有另一个接口 AdvancedMediaPlayer和实现了AdvancedMediaPlayer接口的实体类。该类可以播放vlc和mp4格式的文件。现在想要让AudioPlayer播放其他格式的音频文件。为了实现这个功能,需要创建一个实现了MediaPlayer接口的适配器类MediaAdapter,并使用 AdvancedMediaPlayer 对象来播放所需的格式。AudioPlayer使用适配器类MediaAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。AdapterPatternDemo 类使用AudioPlayer类来播放各种格式。如下图:
(1)创建接口
低级播放器接口如下:
/*
* 低级播放器接口
*/
public interface MediaPlayer {
//默认只能播放音频
void play(String audioType,String fileName);
}
高级播放器接口如下:
/*
* 高级播放器接口
*/
public interface AdvancedMediaPlayer {
//播放mp4格式视频
void playMp4(String fileName);
//播放Vlc格式视频
void playVlc(String fileName);
}
(2)创建高级播放器接口的实现类
该类播放Vlc格式视频:
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playMp4(String fileName) {
// TODO Auto-generated method stub
}
@Override
public void playVlc(String fileName) {
System.out.println("使用vlc格式播放" + fileName + "视频!");
}
}
该类播放mp4格式视频:
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playMp4(String fileName) {
System.out.println("使用mp4格式播放" + fileName + "视频!");
}
@Override
public void playVlc(String fileName) {
// TODO Auto-generated method stub
}
}
(3)创建适配器类
/*
* 适配器
*/
public class MediaAdapter implements MediaPlayer{
//声明一个高级播放器
AdvancedMediaPlayer advancedMediaPlayer;
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("VLC")) {
advancedMediaPlayer.playVlc(fileName);
} else if(audioType.equalsIgnoreCase("MP4")) {
advancedMediaPlayer.playMp4(fileName);
}
}
//构造方法
public MediaAdapter(String audioType) {
if(audioType.equalsIgnoreCase("VLC")) {
advancedMediaPlayer = new VlcPlayer();
} else if(audioType.equalsIgnoreCase("MP4")) {
advancedMediaPlayer = new Mp4Player();
}
}
}
(4)创建低级播放器的实现类
public class AudioPlayer implements MediaPlayer {
//声明一个适配器
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("MP3")){
System.out.println("使用mp3格式播放" + fileName + "音频!");
} else if(audioType.equalsIgnoreCase("VLC") ||
audioType.equalsIgnoreCase("MP4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("播放器不支持" + audioType + "格式!");
}
}
}
(5)测试
使用低级播放器播放mp4格式、vlc格式和其他格式的视频。
public class TestAdapter {
public static void main(String[] args) {
MediaPlayer mediaPlayer = new AudioPlayer();
//播放mp3
mediaPlayer.play("mp3", "云烟成雨.mp3");
//播放mp4
mediaPlayer.play("mp4", "单挑荒野.mp4");
//播放vlc
mediaPlayer.play("vlc", "Java高级视频教程.vlc");
//播放其他
mediaPlayer.play("avi", "凡人修仙传.avi");
}
}
执行,控制台输出如下:
本来MediaPlayer播放器只能播放mp3格式音频,但是加入了一个适配器,在适配器中加入了高级播放器的功能,然后让这个适配器实现MediaPlayer接口,那么低级播放器MediaPlayer就可以通过适配器来使用高级播放器的功能了。
7、总结
适配器模式创建了一个适配器,该适配器是两个不兼容接口之间的桥梁,目的是将一个接口转换成客户希望的另外一个接口。