简介
适配器模式(Adapter Pattern):将一个类的接口变换客户端所期待的另一个接口,从而是原本因接口不匹配而无法一起工作的两个类能够在一起工作,通俗的来说就是连接两个不兼容接口之前的桥梁
优点:
- 可以让两个没有任何关系的类在一起工作;
- 增加了类的透明性;
- 提高了类的复用度;
- 灵活性非常好。
缺点:
- 过多地使用适配器,会让系统非常零乱,不易整体进行把握;
- 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
类图
类适配器类图:
对象适配器类图:
Target:目标角色;该角色定义把其他类装换为何种接口,也就是我们期望的接口。
Adaptee:源角色
Adapter:适配器角色;该模式的核心。
例:我们有两个播放器,一个只能播放MP3格式的文件,另一个可以播放MP4和AVI的格式。现在,我们希望播放MP3格式的也能播放其他格式,这里就轮到适配器模式出场了。类图如下:
java实现
首先创建两个播放器接口及其实现类:
创建MP4以及AVI的播放器:
public interface MediaPlayerMA {
void playMP4(String filename);
void playAVI(String filename);
}
public class AVIPlay implements MediaPlayerMA {
@Override
public void playMP4(String filename) {
}
@Override
public void playAVI(String filename) {
System.out.println("play avi :"+filename);
}
}
public class MP4Play implements MediaPlayerMA {
@Override
public void playMP4(String filename) {
System.out.println("play mp4 :"+filename);
}
@Override
public void playAVI(String filename) {
}
}
创建MP3的播放器
public interface MediaPlayMP3 {
void play(String playType,String filename);
}
public class MP3Play implements MediaPlayMP3 {
@Override
public void play(String playType, String filename) {
if (playType.equalsIgnoreCase("mp3")) {
System.out.println("play avi :" + filename);
} else if (playType.equalsIgnoreCase("avi") || playType.equalsIgnoreCase("mp4")) {
//使用扩展的播放
MediaPlayerAdapter adapter = new MediaPlayerAdapter(playType);
adapter.play(playType, filename);
}else {
System.out.println("don't play :" + filename);
}
}
}
重点:适配器类;这里使用的是对象适配器
public class MediaPlayerAdapter implements MediaPlayMP3 {
private MediaPlayerMA mediaPlayerMA;
//构造函数初始化适配器
public MediaPlayerAdapter(String playType){
if(playType.equalsIgnoreCase("avi")){
mediaPlayerMA = new AVIPlay();
}else if(playType.equalsIgnoreCase("mp4")){
mediaPlayerMA = new MP4Play();
}
}
@Override
public void play(String playType, String filename) {
//判断应该使用哪种播放器
if(playType.equalsIgnoreCase("avi")){
mediaPlayerMA.playAVI(filename);
}else if(playType.equalsIgnoreCase("mp4")){
mediaPlayerMA.playMP4(filename);
}
}
}
场景类
public class Client {
public static void main(String[] args){
MediaPlayMP3 mediaPlayMP3 = new MP3Play();
mediaPlayMP3.play("avi","fs.avi");
mediaPlayMP3.play("MP3","qwe.mp3");
mediaPlayMP3.play("mp4","weewe.mp4");
mediaPlayMP3.play("gif","weewe.gif");
}
}
对象适配器与类适配器之间的区别:
类适配器是类间继承,对象适配器是对象的合成关系,也可以说是关联关系。二者在实际开发中都会经常用到,由于对象适配器是通过类间的关联关系进行耦合,因此在设计时就可以做到比较灵活,比如修补源角色的隐形缺陷,关联其他对象等,而类适配器就只能通过复写源角色方法进行扩展,在实际项目中,对象适配器使用的场景相对较多。