a. 适配器模式剖析
想象一下你正在进行一场全球旅行,来到了一个陌生的国度。你的手机电量不足,却发现电源插座与你的充电器不兼容。这时,一把万能插头适配器出现在你面前,拯救了你的手机。在软件设计世界里,适配器模式就扮演着这样一个角色,它能够将不兼容的接口进行转换,使得原本无法合作的类能够顺利地协同工作。 适配器模式分为两种:类适配器和对象适配器。类适配器通过继承实现,而对象适配器则通过组合来实现。
b. 编写实例:适配器模式实践
假设我们有一个 MediaPlayer 接口,定义了一个 play() 方法,用于播放各种格式的媒体文件。现在我们有一个 AdvancedMediaPlayer 接口,它支持播放更多格式的媒体文件。我们希望在不修改原有 MediaPlayer 的基础上,使其能够播放 AdvancedMediaPlayer 支持的格式。为此,我们可以引入一个适配器。 首先,定义 MediaPlayer 和 AdvancedMediaPlayer 接口:
public interface MediaPlayer {
void play(String audioType, String fileName);
}
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
然后,创建实现 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) {
// Do nothing
}
}
public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// Do nothing
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: " + fileName);
}
}
接下来,创建适配器类,使得 MediaPlayer 能够使用 AdvancedMediaPlayer:
public class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedMediaPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMediaPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMediaPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMediaPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMediaPlayer.playMp4(fileName);
}
}
}
最后,创建一个 AudioPlayer 类,它实现了 MediaPlayer 接口,通过 MediaAdapter 类适配 AdvancedMediaPlayer:
public class AudioPlayer implements MediaPlayer {
private MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file. Name: " + fileName);
} 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.");
}
}
}
现在,我们可以通过 AudioPlayer 类来播放 mp3、vlc 和 mp4 格式的文件:
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");
}
}
c. 权衡利弊:适配器模式分析
优点:
1、提高了类的复用性。原本无法一起工作的类可以通过适配器进行协同。 2、适配器模式可以实现解耦,提高了代码的可扩展性。 3、可以透明地使用新接口,使得客户端不需要关心适配过程。
缺点:
1、适配器模式可能会导致系统变得复杂,增加了代码的阅读难度。 2、过多地使用适配器可能会使得系统结构变得混乱。
d. 适配器模式在开源框架中的应用
在 Spring 框架中,适配器模式被广泛应用。例如,Spring MVC 中的 HandlerAdapter 就用到了适配器模式。HandlerAdapter 负责将不同类型的处理器(Controller)适配为统一的接口,使得 DispatcherServlet 能够处理各种类型的请求。 以下是 Spring 框架中一个简化版的 HandlerAdapter 示例:
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
通过实现 HandlerAdapter 接口,可以支持多种类型的处理器。这样,开发者可以方便地扩展和定制自己的处理器类型,而无需修改 DispatcherServlet 的代码。
总结:
适配器模式为解决不同接口之间的兼容性问题提供了优雅的解决方案。通过理解和运用适配器模式,我们可以让原本无法协同工作的类顺利地合作,提高代码的复用性和可扩展性。同时,要注意适配器模式可能带来的系统复杂性和混乱。
标签:十一,String,适配器,桥梁,fileName,void,audioType,public From: https://blog.51cto.com/u_13616584/6237850