Skip to content

适配器

更新: 6/28/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);
        }
    }
}

优缺点

优点:

  1. 解耦目标类和被适配者类
  2. 复用现有类,无需修改原有代码
  3. 符合开闭原则(对扩展开放,对修改关闭)

缺点:

  1. 过度使用会使系统结构复杂化
  2. 增加代码理解难度
  3. 某些语言不支持多重继承(限制类适配器使用)

应用场景

  1. 集成第三方库或遗留系统
  2. 统一多个类接口
  3. 创建可复用类与不相关类协同工作
  4. 系统扩展需要兼容旧接口

与其他模式的关系

  • 与桥接模式:都涉及接口转换,但桥接关注抽象与实现分离
  • 与装饰器模式:都使用包装,但装饰器增强功能而适配器转换接口
  • 与外观模式:适配器针对单个对象,外观针对整个子系统
  • 与代理模式:代理控制访问,适配器转换接口

JDK 中的适配器模式

  1. java.util.Arrays#asList():数组转 List 适配器
  2. java.io.InputStreamReader(InputStream):字节流到字符流适配器
  3. java.util.Collections#list(Enumeration):Enumeration 转 List 适配器

注意事项

  1. 优先使用对象适配器(组合优于继承)
  2. 避免过度设计,只在真正需要接口转换时使用
  3. 考虑适配器性能开销(多层包装可能影响性能)
  4. 注意双向适配器可能导致循环引用问题

贡献者

The avatar of contributor named as AKAcxp AKAcxp

页面历史