定义:将一个类的接口转换成客户希望的另外一个接口,作为两个不兼容的接口之间的桥梁
优劣:
- 优点:可以让没有关联的两个类在一起运行,提高了类的复用,灵活性好
- 缺点:过多地使用适配器,会让系统非常零乱,系统整体不易把控;由于Java只能继承一个父类地特性,所以至多只能适配一个适配者类,而且目标类必须是抽象类
使用场景:修改一个正常运行的系统接口,应该考虑使用适配器模式
注意事项:适配器不是在详细设计时添加的,而是解决正在运行的项目的问题时添加
与装饰器模式的区别:装饰器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的很不一一样。适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。
而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的。
示例:使一个播放mp3格式的播放器也能播放(适配)mp4和vlc格式的文件
示意图:
类说明:
- MediaPlayer接口和AudioPlayer实现类是播放mp3格式的播放器
- AdvancedMediaPlayer接口和两个实现类类VlcPlayer、Mp4Player是播放vlc和mp4格式的播放器
- MediaAdapter类是实现MediaPlayer接口并且连接AdvancedMedalPlayer接口功能的适配器类
- AdapterPattern测试类
示例:
package designPattern.adapter;
public interface MediaPlayer {
void play(String audioType, String fileName);
}
package designPattern.adapter;
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
package designPattern.adapter;
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
}
@Override
public void playMp4(String fileName) {
System.out.println("播放MP4文件:" + fileName);
}
}
package designPattern.adapter;
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("播放vlc文件:" + fileName);
}
@Override
public void playMp4(String fileName) {
// nothing
}
}
package designPattern.adapter;
/**
* 适配器
* @author sunlh
*
*/
public class MediaAdapter implements MediaPlayer{
AdvancedMediaPlayer advancedMediaPlayer;
public MediaAdapter(String audioType) {
if ("vlc".equalsIgnoreCase(audioType)) {
advancedMediaPlayer = new VlcPlayer();
} else if ("mp4".equalsIgnoreCase(audioType)) {
advancedMediaPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if ("vlc".equalsIgnoreCase(audioType)) {
advancedMediaPlayer.playVlc(fileName);
} else if ("mp4".equalsIgnoreCase(audioType)) {
advancedMediaPlayer.playMp4(fileName);
}
}
}
package designPattern.adapter;
public class AudioPlayer implements MediaPlayer {
MediaPlayer mediaPlayer;
@Override
public void play(String audioType, String fileName) {
//对自身mp3文件的支持
if ("mp3".equalsIgnoreCase(audioType)) {
System.out.println("播放mp3文件:" + fileName);
}
// 对其他文件格式的支持
else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)) {
mediaPlayer = new MediaAdapter(audioType);
mediaPlayer.play(audioType, fileName);
}
else {
System.out.println("无效的播放文件格式");
}
}
}
package designPattern.adapter;
public class TestDemo {
public static void main(String[] args) {
MediaPlayer player = new AudioPlayer();
player.play("mp3", "That girl");
player.play("mp4", "警察故事");
player.play("vlc", "城市猎人");
player.play("png", "山水图片");
}
}
执行结果
播放mp3文件:That girl
播放MP4文件:警察故事
播放vlc文件:城市猎人
无效的播放文件格式