适配器
更新: 6/22/2025 字数: 0 字 时长: 0 分钟
定义
适配器模式 (Adapter Pattern) 将一个类的接口转换成客户期望的另一个接口,使原本不兼容的类可以协同工作。适配器模式通过包装对象解决接口不匹配问题。
角色
- 目标接口 (Target):客户端期望的接口
- 适配器 (Adapter):实现目标接口,包装被适配者
- 被适配者 (Adaptee):需要被适配的现有组件
实现
类适配器(继承实现)
java
// 目标接口
public interface MediaPlayer {
void play(String audioType, String fileName);
}
// 被适配者
public class AdvancedMediaPlayer {
public void playVlc(String fileName) {
System.out.println("Playing vlc file: " + fileName);
}
public void playMp4(String fileName) {
System.out.println("Playing mp4 file: " + fileName);
}
}
// 适配器(继承被适配者)
public class MediaAdapter extends AdvancedMediaPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
playMp4(fileName);
}
}
}
对象适配器(组合实现)
java
// 适配器(组合被适配者)
public class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
优缺点
优点:
- 解耦目标类和被适配者类
- 复用现有类,无需修改原有代码
- 符合开闭原则(对扩展开放,对修改关闭)
缺点:
- 过度使用会使系统结构复杂化
- 增加代码理解难度
- 某些语言不支持多重继承(限制类适配器使用)
应用场景
- 集成第三方库或遗留系统
- 统一多个类接口
- 创建可复用类与不相关类协同工作
- 系统扩展需要兼容旧接口
与其他模式的关系
- 与桥接模式:都涉及接口转换,但桥接关注抽象与实现分离
- 与装饰器模式:都使用包装,但装饰器增强功能而适配器转换接口
- 与外观模式:适配器针对单个对象,外观针对整个子系统
- 与代理模式:代理控制访问,适配器转换接口
JDK 中的适配器模式
java.util.Arrays#asList()
:数组转 List 适配器java.io.InputStreamReader(InputStream)
:字节流到字符流适配器java.util.Collections#list(Enumeration)
:Enumeration 转 List 适配器
注意事项
- 优先使用对象适配器(组合优于继承)
- 避免过度设计,只在真正需要接口转换时使用
- 考虑适配器性能开销(多层包装可能影响性能)
- 注意双向适配器可能导致循环引用问题