设计模式之适配器模式
类的关系
UML类图
大致理解
我们有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的实体类 AudioPlayer。默认情况下,AudioPlayer 可以播放 mp3 格式的音频文件。
我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的实体类。该类可以播放 mp5 和 mp4 格式的文件。
我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 对象(接口)来播放所需的格式。
代码分析
最原始的接口MediaPlayer
public interface MediaPlayer {
public void play(String audioType, String fileName);
}扩展功能的接口 AdvancedMediaPlayer
public interface AdvancedMediaPlayer {
public void playMp5(String fileName);
public void playMp4(String fileName);
}先理解扩展功能的实现类(2个)
public class Mp5Player implements AdvancedMediaPlayer{
@Override
public void playMp5(String fileName) {
System.out.println("播放Mp5文件: "+ fileName);
}
@Override
public void playMp4(String fileName) {
//什么也不做
}
}
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playMp5(String fileName) {
//什么也不做
}
@Override
public void playMp4(String fileName) {
System.out.println("播放MP4文件 "+ fileName);
}
}最原始mp3功能的实现类(后续会迭代)
public class AudioPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if(audioType.equals("mp3")){
System.out.println("播放Mp3: "+ fileName);
}
else{
System.out.println("以下 "+
audioType + "格式不支持");
}
}
}显然,如果没有适配器,最原始和扩展功能是无法联系在一起的,因此此时我们加入适配器后,要将相应的代码进行修改
因此先理解适配器的实现
可以清晰的看到,适配器中,有一个扩展接口AdvancedMediaPlayer对象,根据传入的参数,判断使用哪个扩展功能。
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedPlayer;
//构造器
public MediaAdapter(String audioType){
if(audioType.equals("mp5") ){
advancedPlayer = new Mp5Player();
} else if (audioType.equals("mp4")){
advancedPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if(audioType.equals("mp5")){
advancedPlayer.playMp5(fileName);
}else if(audioType.equals("mp4")){
advancedPlayer.playMp4(fileName);
}
}
}重中之重 基础实现类代码迭代
我们添加了适配器,必然要修改之前实现的AudioPlayer,也就是普通播放功能的类,因为我们期望普通播放类中可以完成扩展功能。(原本只能播放mp3现在能放mp5)
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if(audioType.equals("mp3")){
System.out.println("播放Mp3: "+ fileName);
}
//mediaAdapter 提供了播放其他文件格式的支持
else if(audioType.equals("mp5")
|| audioType.equals("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("以下 "+
audioType + "格式不支持");
}
}
}可以看到,当传入的是Mp4时,我们会new一个适配器对象处理,并告诉它具体格式是什么(构造器传参数),然后调用对应的播放功能,也就是说,在基础实现类中,我们会新建一个适配器对象,然后用适配器去实现扩展的功能。
Demo类主方法
public class Demo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "音乐.mp3");
audioPlayer.play("mp4", "视频.mp4");
audioPlayer.play("mp5", "进阶视频.mp5");
audioPlayer.play("avi", "开车.avi");
}
}测试结果:
播放Mp3: 音乐.mp3 播放MP4文件 视频.mp4 播放Mp5文件: 进阶视频.mp5 以下 avi格式不支持
总结:
- 当你学习设计模式的时候,基础要打牢,这里的多态体现的淋漓尽致。适配器中会new接口对象,然后利用多态拿到具体的实现类,并完成播放功能,真的是妙妙妙啊。
- 另外我们可以看到,中间有一个迭代过程,也说明了适配器模式不是在项目一开始就设计好的,而是解决正在服役的项目需要扩展功能的时候出现的。并且这个扩展功能并不是当前类的扩展,而是其他类,这里的扩展是指整个系统上的扩展。
- 优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。
- 缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握。明明调用了这个接口,却可以实现其他接口的功能。
初识设计模式 文章被收录于专栏
第一次学设计模式,学的不够透彻,但依旧有些心得值得做做笔记

