适配器模式

结构型模式

访问次数: 10

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

类图
classDiagram
    class Target {
        <<interface>>
        +request()
    }
    class Adaptee {
        +specificRequest()
    }
    class Adapter {
        -adaptee: Adaptee
        +request()
    }
    class Client {
        -target: Target
        +doSomething()
    }
    Target <|-- Adapter
    Adapter --> Adaptee
    Client --> Target
源代码示例
// 目标接口
interface Target {
    void request();
}

// 被适配者
class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee specific request");
    }
}

// 适配器
class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

// 客户端
class Client {
    private Target target;
    
    public Client(Target target) {
        this.target = target;
    }
    
    public void doSomething() {
        target.request();
    }
}
# Python代码待添加
应用场景
当需要使用一个已经存在的类,但其接口不符合要求时。应用场景包括: 1)第三方库的接口与系统接口不匹配,需要适配器进行转换(如使用第三方支付SDK) 2)遗留系统集成,将旧的系统接口适配到新的系统架构中 3)数据格式转换,将不同格式的数据(JSON、XML、CSV)转换为统一的内部格式 4)硬件设备驱动,将不同厂商的设备接口适配到统一的设备管理接口 5)API版本兼容,将新版本API适配到旧版本接口,保持向后兼容性 6)跨平台适配,将特定平台的API适配到跨平台的统一接口
精选场景详解 —— 第三方支付 SDK:接口不匹配时的适配
问题背景

系统内部统一用 pay(orderId, amount),但支付宝 SDK 方法是 tradePay(bizContent),微信是 unifiedOrder(req)。不能改第三方源码,又不能让业务层直接依赖多家 SDK。

模式如何解决
选用对象适配器:定义目标接口 PaymentGateway;为每个 SDK 写 Adapter,内部持有 Adaptee(第三方客户端),在 pay 方法里完成参数转换并调用 SDK。 效果: 1)业务只依赖稳定的目标接口; 2)第三方变更被隔离在适配器内; 3)符合「复用已有类但接口不符」的典型动机。 类适配器(继承 Adaptee)较少用;优先组合(持有 Adaptee)更灵活。
场景模型(角色映射)

将模式中的抽象角色映射到该业务领域的具体类:

classDiagram
    class PaymentGateway {
        <<interface>>
        +pay(orderId: String, amount: decimal) PayResult
    }
    class AlipaySdkClient {
        +tradePay(bizContent: String) String
    }
    class AlipayGatewayAdapter {
        -sdk: AlipaySdkClient
        +pay(orderId: String, amount: decimal) PayResult
    }
    class WeChatSdkClient {
        +unifiedOrder(req: WxPayRequest) WxPayResponse
    }
    class WeChatGatewayAdapter {
        -sdk: WeChatSdkClient
        +pay(orderId: String, amount: decimal) PayResult
    }
    class OrderPayService {
        -gateway: PaymentGateway
        +payOrder(order: Order)
    }
    PaymentGateway <|.. AlipayGatewayAdapter
    PaymentGateway <|.. WeChatGatewayAdapter
    AlipayGatewayAdapter --> AlipaySdkClient
    WeChatGatewayAdapter --> WeChatSdkClient
    OrderPayService --> PaymentGateway