~/app/articles/NORMAL

cat article/37.md

适配器模式 (Adapter) 全面讲解

学习笔记
设计模式
适配器模式
Java
面向对象
软件设计
编程实践

本文全面讲解了适配器模式,包括其定义、适用场景、实现方式以及在实际编程中的应用,旨在帮助读者深入理解并掌握这一重要的设计模式。

date: 2025-06-22T20:04:00 tags:

  • 设计模式
  • Java
  • 面向对象
  • 复习

适配器模式 (Adapter) 全面讲解


1. 什么是适配器模式?

适配器模式是结构型设计模式,用于让不兼容的接口能够协同工作。

  • 核心思想:通过一个中间层(适配器)转换接口,类似电源插头转换器。
  • 类比:
    • Type-C转3.5mm耳机接口
    • 翻译官(连接语言不通的两人)

🔹 适用场景

  • 整合第三方库/旧系统时接口不匹配。
  • 需要统一多个类的接口(如不同品牌的充电协议)。

2. 为什么需要适配器模式?

问题场景

假设有一个新系统调用ModernPrinter打印,但旧系统的LegacyPrinter接口不同:

// 新系统的接口(目标接口)
interface ModernPrinter {
    void print(String text);
}

// 旧系统的类(需适配的类)
class LegacyPrinter {
    void printDocument(String content, int copies) {
        for (int i = 0; i < copies; i++) {
            System.out.println("旧打印机打印: " + content);
        }
    }
}

问题:无法直接调用LegacyPrinter,因为接口不兼容!


3. 适配器模式的两种实现

3.1 类适配器(继承方式)

通过继承旧类实现适配(需支持多继承,Java不适用,但可模拟)。

// 适配器类(继承LegacyPrinter并实现ModernPrinter)
class ClassAdapter extends LegacyPrinter implements ModernPrinter {
    @Override
    public void print(String text) {
        printDocument(text, 1); // 调用父类方法,固定copies=1
    }
}

3.2 对象适配器(组合方式,推荐)

通过持有旧类的实例实现适配(更灵活)。

class ObjectAdapter implements ModernPrinter {
    private LegacyPrinter legacyPrinter; // 组合旧类

    public ObjectAdapter(LegacyPrinter legacyPrinter) {
        this.legacyPrinter = legacyPrinter;
    }

    @Override
    public void print(String text) {
        legacyPrinter.printDocument(text, 1); // 委托给旧类
    }
}

4. 完整示例代码(对象适配器)

步骤1:定义目标接口(新系统)

interface ModernPrinter {
    void print(String text);
}

步骤2:定义被适配者(旧系统)

class LegacyPrinter {
    void printDocument(String content, int copies) {
        for (int i = 0; i < copies; i++) {
            System.out.println("旧打印机打印: " + content);
        }
    }
}

步骤3:实现适配器

class PrinterAdapter implements ModernPrinter {
    private LegacyPrinter legacyPrinter;

    public PrinterAdapter(LegacyPrinter legacyPrinter) {
        this.legacyPrinter = legacyPrinter;
    }

    @Override
    public void print(String text) {
        legacyPrinter.printDocument(text, 1); // 适配逻辑
    }
}

步骤4:客户端调用

public class Client {
    public static void main(String[] args) {
        // 旧系统对象
        LegacyPrinter legacyPrinter = new LegacyPrinter();
        
        // 适配器转换
        ModernPrinter adapter = new PrinterAdapter(legacyPrinter);
        
        // 新系统统一调用
        adapter.print("Hello World"); 
        // 输出:旧打印机打印: Hello World
    }
}

5. 关键点总结

对比项类适配器对象适配器(推荐)
实现方式继承被适配者组合被适配者
灵活性低(Java不支持多继承)高(可适配多个不同类)
复杂度简单略高

🔹 适配器模式的优点

  • 解耦:客户端与被适配者无需直接交互。
  • 复用性:可复用现有类(如旧系统代码)。

🔹 常见应用

  • Java I/O中的InputStreamReader(适配InputStream到Reader)。
  • Spring MVC的HandlerAdapter(适配不同Controller接口)。

6. 互动实践

问题1:以下代码是哪种适配器?

class Adapter extends OldSystem implements NewInterface {
    @Override
    public void newMethod() {
        oldMethod();
    }
}

答案:类适配器(通过继承实现)。

问题2:如何用对象适配器实现USB转Type-C?

任务:

  • 被适配者:USB类(有transferData()方法)。
  • 目标接口:TypeC(需fastTransfer()方法)。
  • 补全适配器代码:
class USBToTypeCAdapter implements TypeC {
    private USB usb;
    // 你的代码...
}

7. 考试练习题

题目1(概念题)

适配器模式的主要作用是?
A. 扩展对象功能
B. 转换接口以便复用
C. 隐藏对象创建细节
D. 优化算法性能

答案:B


题目2(代码填空)

补全对象适配器模式的代码:

interface NewService {
    void execute();
}

class OldService {
    void run() { System.out.println("旧服务运行"); }
}

class Adapter implements NewService {
    private OldService oldService;
    
    public Adapter(____ oldService) {  // 填空1
        this.oldService = oldService;
    }

    @Override
    public void execute() {
        ____.run();  // 填空2
    }
}

答案:

  1. OldService
  2. oldService

题目3(设计题)

现有两个不兼容的支付接口:

  • 支付宝:Alipay.pay(double money)
  • 微信支付:WeChatPay.payment(double amount)
    设计一个适配器,统一调用接口为Payment.pay(double money)。
$ comments --list (0)

// not signed in


// no comments yet