Skip to content

适配器

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

优缺点

优点:

  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 LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史