Adapter 模式
将一个类的接口转换成调用方期望的另一种接口,使原本因接口不兼容而无法协作的类可以协同工作。接口必须发生变化——这是与 Proxy(接口不变)和 Decorator(接口不变)的核心区分标准。
定义
Adapter 模式(适配器模式)将一个接口翻译成另一种接口。调用方只知道目标接口,Adapter 在内部把调用转换成被适配对象能理解的格式。
区分标准:接口是否发生变化。
Proxy 和 Decorator 都"包装"原对象且接口不变;Adapter 做接口翻译,不委托原对象的方法。
vercel/ai 中的典型案例
案例一:convertToOpenAIChatMessages(单函数 Adapter)
// 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)
四套实现是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]] — 另一种扩展策略,不改变接口而是预留扩展槽