Adapter 模式

将一个类的接口转换成调用方期望的另一种接口,使原本因接口不兼容而无法协作的类可以协同工作。接口必须发生变化——这是与 Proxy(接口不变)和 Decorator(接口不变)的核心区分标准。

定义

Adapter 模式(适配器模式)将一个接口翻译成另一种接口。调用方只知道目标接口,Adapter 在内部把调用转换成被适配对象能理解的格式。

区分标准:接口是否发生变化。

模式接口变化是否委托原对象核心用途
Adapter✅ 有(源接口 → 目标接口)❌ 不委托,只做数据转换格式/协议翻译
Proxy❌ 无(同接口)✅ 透传或拦截后透传版本兼容、访问控制
Decorator❌ 无(同接口)✅ 持有引用,增强行为横切关注点叠加

Proxy 和 Decorator 都"包装"原对象且接口不变;Adapter 做接口翻译,不委托原对象的方法。

vercel/ai 中的典型案例

案例一:convertToOpenAIChatMessages(单函数 Adapter)

typescript
// openai-chat-language-model.ts:L129
function convertToOpenAIChatMessages(
  prompt: LanguageModelV4Prompt    // 输入:标准接口格式
): OpenAIChatPrompt {              // 输出:OpenAI API 专有格式
  // 纯数据转换,不委托任何对象的方法
}

输入是 vercel/ai 标准的 prompt 结构(LanguageModelV4Prompt),输出是 OpenAI Chat Completions API 能接受的 JSON 格式(OpenAIChatPrompt)。这是一个纯函数 Adapter——没有包装对象,只有格式转换。

案例二:OpenAI 四套 Provider 实现(类 Adapter)

实现类源接口(OpenAI API)目标接口
OpenAIChatLanguageModelChat Completions APILanguageModelV4
OpenAICompletionLanguageModelLegacy Completions APILanguageModelV4
OpenAIResponsesLanguageModelResponses APILanguageModelV4
OpenAIRealtimeModelRealtime APILanguageModelV4

四套实现是Multiple Adapters for One Target Interface——同一个 LanguageModelV4 目标接口,四种 OpenAI API 路径各有一个 Adapter 实现。极薄接口(只有 doGenerate + doStream 两个方法)让这四个 Adapter 的实现成本极低;若目标接口有 10 个方法,实现成本会是现在的 5 倍。

变体注意:V2→V3 的重量 Proxy 是"Proxy 包装 Adapter 逻辑"

as-language-model-v3.ts 用 JavaScript Proxy 语法,但在拦截的 doGenerate 里做了 Adapter 语义的数据转换(usage 结构重构)。选 Proxy 而不是纯 Adapter 是工程原因:Proxy 能"有的属性拦截转换,其余全透传",纯 Adapter 要实现所有方法。这是模式的变体,不是标准 Adapter,也不是标准 Proxy。

关联知识

  • [[proxy]] — 接口不变的包装模式,与 Adapter 的核心区别在于接口是否变化
  • [[namespace-extension]] — 另一种扩展策略,不改变接口而是预留扩展槽