自学教程 学编程从这里开始

适配器模式

《适配器模式》|设计模式系列第07篇

系列:结构型模式 · 适配器模式(Adapter Pattern)
关键词:转换接口、兼容旧系统、包装、适配器、类适配器、对象适配器

一、什么是适配器模式

适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

属于结构型设计模式。

简单理解:
适配器就像电源转换插头。国外电器插头规格和国内插座不一样,不能直接使用;增加一个转换插头(适配器),就能把原有接口转换成目标接口,双方正常工作。适配器不修改原有代码,只做接口转换。

核心意图
包装原有类,转换接口,让不兼容的接口可以协同工作。

适用场景

  1. 需要使用现有类,但它的接口不符合你的需求
  2. 整合第三方组件、遗留老系统,新旧接口不匹配
  3. 统一多个类的接口,客户端面向统一接口调用
  4. 复用现有组件,不想修改原有代码

⚠️ 缺点预警:过多使用适配器,会增加代码复杂度;如果能提前重构接口,优先重构而非适配器。

二、UML结构图

角色划分:

  1. Target(目标接口):客户端期望使用的接口
  2. Adaptee(被适配者):已经存在、接口不兼容的现有类
  3. Adapter(适配器):实现Target,内部包装Adaptee,做接口转换
  4. Client(客户端):依赖Target接口,调用适配器

适配器分两类:对象适配器(组合,推荐)、类适配器(继承,Java不支持多继承,受限)

三、Java 完整示例

场景:播放器,客户端期望统一 play() 接口。老的MP4播放器方法名叫 playMp4(),接口不兼容,使用适配器做适配。

1. 目标接口 Target

// 目标接口:客户端期望的播放接口
public interface MediaPlayer {
    void play(String fileName);
}

2. 被适配者 Adaptee

// 已存在的老MP4播放器,接口不匹配
public class Mp4Player {
    public void playMp4(String fileName) {
        System.out.println("播放MP4文件:" + fileName);
    }
}

3. 对象适配器 Adapter(推荐,组合方式)

// 适配器:包装Mp4Player,实现目标接口
public class MediaAdapter implements MediaPlayer {
    private Mp4Player mp4Player;

    public MediaAdapter(Mp4Player mp4Player) {
        this.mp4Player = mp4Player;
    }

    @Override
    public void play(String fileName) {
        // 接口转换,调用被适配者方法
        mp4Player.playMp4(fileName);
    }
}

4. 客户端调用

public class Client {
    public static void main(String[] args) {
        Mp4Player mp4Player = new Mp4Player();
        MediaPlayer mediaPlayer = new MediaAdapter(mp4Player);
        mediaPlayer.play("demo.mp4");
    }
}

补充:类适配器(Java受限)

类适配器依靠继承被适配者实现适配。Java是单继承,限制很大,实际开发极少使用。

// Java中仅作演示,不推荐
public class ClassMediaAdapter extends Mp4Player implements MediaPlayer {
    @Override
    public void play(String fileName) {
        playMp4(fileName);
    }
}

四、对象适配器 vs 类适配器

类型实现方式优点缺点
对象适配器组合(持有Adaptee对象)松耦合,适配任意Adaptee子类需要包装对象
类适配器继承Adaptee可以重写父类方法单继承限制,耦合高

开发原则:优先使用对象适配器(组合),符合合成复用原则。

五、优缺点总结

✅ 优点

  1. 复用现有代码,不需要修改原有类
  2. 解耦客户端与被适配者,客户端只依赖目标接口
  3. 灵活,一个适配器可以适配多个被适配者

❌ 缺点

  1. 增加额外适配器类,代码复杂度上升
  2. 接口转换需要额外逻辑,少量性能损耗
  3. 过度使用会增加系统理解成本

六、框架源码应用

  • JDK java.io.InputStreamReader:字节流转字符流,InputStream是被适配者,Reader是目标接口
  • Spring HandlerAdapter:适配不同类型Controller
  • SpringMVC 各种 Adapter 组件

七、小结

适配器核心:做接口转换,兼容已有代码,不修改原有实现。
记住:适配器是包装转换接口,不是增强功能;和装饰器模式容易混淆,装饰器是增强原有对象能力,适配器是改变接口。

标签:

0 条笔记