适配器模式 logo

适配器模式

Organization
microwind
适配器模式

将一个类的接口转换为客户端期望的另一个接口,解决不兼容问题。

Overview

Publishermicrowind
Repositoryai-skills
Skill name适配器模式
Stars
93
Forks
25
Bundled files
3
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 3 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by microwind on GitHub. Read the source before you install it.

Installation

Install the 适配器模式 AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/microwind/ai-skills/tree/main/design-patterns/adapter-pattern
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/microwind/ai-skills.git /tmp/ai-skills
mkdir -p .claude/skills
cp -r /tmp/ai-skills/design-patterns/adapter-pattern .claude/skills/microwind-23
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable 适配器模式 in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads 适配器模式 on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so 适配器模式 is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

适配器模式 (Adapter Pattern)

核心概念

Adapter是一种结构型设计模式,用于将一个不兼容的类的接口转换为客户端期望的接口。适配器充当"翻译"角色,使得原本无法协同工作的对象可以一起工作。

核心原则:

  • 解决接口不兼容问题
  • 无需修改原有接口即可集成新对象
  • 促进代码复用,延长类的生命周期
  • 支持第三方库的集成

适配方式:

  • 类适配 (Class Adapter) - 通过继承实现
  • 对象适配 (Object Adapter) - 通过组合实现 ⭐ 推荐

何时使用

始终使用:

  • 需要使用第三方库但接口不兼容
  • 旧系统与新系统集成
  • 多个子系统接口不统一
  • 希望不修改原有代码的情况下扩展功能

触发短语:

  • "这个库的API不适配我们的系统"
  • "需要集成遗留系统,但接口完全不同"
  • "期望一个统一的接口来操作不同的实现"

典型场景:

场景需适配的目标接口适配器
支付网关整合Alipay, WeChat SDKPaymentGatewayAlipayAdapter
日期处理java.util.Date, LocalDateTimeDateConverterDateAdapter
数据库驱动MySQL, PostgreSQLJdbcConnectionDbAdapter
UI组件库第三方组件内部UI接口ComponentAdapter

4个实现方法

方法1: 对象适配器 (Object Adapter) ⭐推荐

通过组合原对象,适配其接口到目标接口。

java
// 不兼容的现有接口 (第三方库)
public class LegacyPaymentSystem {
    public String processPayment(double amount) {
        return "支付宝处理: " + amount;
    }
}

// 目标接口 (系统期望)
public interface PaymentGateway {
    boolean pay(double amount);
    String getStatus();
}

// 对象适配器 - 通过组合
public class PaymentAdapter implements PaymentGateway {
    private LegacyPaymentSystem legacySystem;
    
    public PaymentAdapter(LegacyPaymentSystem system) {
        this.legacySystem = system;
    }
    
    @Override
    public boolean pay(double amount) {
        try {
            String result = legacySystem.processPayment(amount);
            System.out.println("适配结果: " + result);
            return result.contains("成功");
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public String getStatus() {
        return "已支付";
    }
}

// 使用
LegacyPaymentSystem legacy = new LegacyPaymentSystem();
PaymentGateway adapter = new PaymentAdapter(legacy);
adapter.pay(100.0);

优点: 灵活,不修改原类,可适配多个接口 缺点: 需要包装对象

方法2: 类适配器 (Class Adapter)

通过继承原类来适配。

java
// 类适配器 - 通过继承
public class DirectPaymentAdapter extends LegacyPaymentSystem 
        implements PaymentGateway {
    
    @Override
    public boolean pay(double amount) {
        String result = super.processPayment(amount);
        return result.contains("成功");
    }
    
    @Override
    public String getStatus() {
        return "已处理";
    }
}

// 使用
PaymentGateway adapter = new DirectPaymentAdapter();
adapter.pay(100.0);

优点: 简单直接 缺点: 受限于Java单继承,不够灵活

方法3: 双向适配器 (Two-Way Adapter)

同时适配两个不兼容的接口。

java
// 两个不兼容的接口
public interface ChinesePayment {
    String payWithUnifiedOrder(double amount);
}

public interface WeternPayment {
    boolean processPayment(double amount);
}

// 双向适配器
public class BidirectionalAdapter implements ChinesePayment, WeternPayment {
    private Object target;
    
    public BidirectionalAdapter(Object target) {
        this.target = target;
    }
    
    @Override
    public String payWithUnifiedOrder(double amount) {
        // 适配到 WeternPayment 接口
        if (target instanceof WeternPayment) {
            boolean success = ((WeternPayment) target).processPayment(amount);
            return success ? "成功" : "失败";
        }
        return "不支持";
    }
    
    @Override
    public boolean processPayment(double amount) {
        // 适配到 ChinesePayment 接口
        if (target instanceof ChinesePayment) {
            String result = ((ChinesePayment) target).payWithUnifiedOrder(amount);
            return result.contains("成功");
        }
        return false;
    }
}

方法4: 装饰改进的适配器

在适配的同时添加额外功能。

java
public class EnhancedPaymentAdapter implements PaymentGateway {
    private LegacyPaymentSystem legacy;
    private List<PaymentInterceptor> interceptors = new ArrayList<>();
    
    public EnhancedPaymentAdapter(LegacyPaymentSystem legacy) {
        this.legacy = legacy;
    }
    
    public void addInterceptor(PaymentInterceptor interceptor) {
        interceptors.add(interceptor);
    }
    
    @Override
    public boolean pay(double amount) {
        // 前拦截器
        for (PaymentInterceptor interceptor : interceptors) {
            if (!interceptor.beforePay(amount)) {
                return false;
            }
        }
        
        // 适配的支付
        boolean result = legacyProcessPayment(amount);
        
        // 后拦截器
        for (PaymentInterceptor interceptor : interceptors) {
            interceptor.afterPay(amount, result);
        }
        
        return result;
    }
    
    private boolean legacyProcessPayment(double amount) {
        try {
            String response = legacy.processPayment(amount);
            return response.contains("成功");
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public String getStatus() { return "已处理"; }
}

public interface PaymentInterceptor {
    boolean beforePay(double amount);
    void afterPay(double amount, boolean success);
}

// 使用
EnhancedPaymentAdapter adapter = new EnhancedPaymentAdapter(legacy);
adapter.addInterceptor(new LoggingInterceptor());
adapter.addInterceptor(new ValidationInterceptor());
adapter.pay(100.0);

常见问题与解决方案

❌ 问题1: 适配器性能开销

症状: 频繁调用适配器,性能下降。

根本原因: 每次调用都经过一层包装,特别是双适配。

解决方案:

java
// ✅ 缓存适配后的对象
public class CachedPaymentAdapter implements PaymentGateway {
    private Map<String, Object> cache = new ConcurrentHashMap<>();
    private LegacyPaymentSystem legacy;
    
    @Override
    public boolean pay(double amount) {
        String key = "payment_" + amount;
        Object cached = cache.get(key);
        
        if (cached != null) {
            return (Boolean) cached;
        }
        
        boolean result = legacyProcessPayment(amount);
        cache.put(key, result);
        return result;
    }
    
    private boolean legacyProcessPayment(double amount) {
        return legacy.processPayment(amount).contains("成功");
    }
    
    @Override
    public String getStatus() { return "已处理"; }
}

❌ 问题2: 接口不完全兼容

症状: 适配器无法完整适配所有功能。

根本原因: 被适配类功能集合与目标接口功能集合不匹配。

解决方案:

java
// ✅ 分离适配与补充功能
public interface FullPaymentGateway extends PaymentGateway {
    boolean refund(String transactionId);
    List<Transaction> getHistory();
}

public class CompletePaymentAdapter implements FullPaymentGateway {
    private LegacyPaymentSystem legacy;
    private List<Transaction> localHistory = new ArrayList<>();
    
    @Override
    public boolean pay(double amount) {
        boolean result = legacy.processPayment(amount).contains("成功");
        if (result) {
            localHistory.add(new Transaction(amount, System.currentTimeMillis()));
        }
        return result;
    }
    
    @Override
    public boolean refund(String transactionId) {
        // 补充功能: 旧系统不支持退款
        localHistory.removeIf(t -> t.getId().equals(transactionId));
        return true;
    }
    
    @Override
    public List<Transaction> getHistory() {
        return new ArrayList<>(localHistory);
    }
    
    @Override
    public String getStatus() { return "已处理"; }
}

❌ 问题3: 第三方库版本变更导致适配器失效

症状: 升级第三方库后,适配器报错。

根本原因: 适配器强耦合于特定版本的第三方库。

解决方案:

java
// ✅ 使用策略模式支持多版本
public interface PaymentAdapterStrategy {
    boolean pay(double amount);
}

public class AlipayV1Adapter implements PaymentAdapterStrategy {
    private LegacyPaymentSystem legacyV1;
    
    @Override
    public boolean pay(double amount) {
        return legacyV1.processPayment(amount).contains("成功");
    }
}

public class AlipayV2Adapter implements PaymentAdapterStrategy {
    private NewPaymentSystem newV2;
    
    @Override
    public boolean pay(double amount) {
        return newV2.executePayment(amount) == PaymentResult.SUCCESS;
    }
}

public class VersionAwareAdapter implements PaymentGateway {
    private PaymentAdapterStrategy strategy;
    
    public VersionAwareAdapter(String version) {
        if ("1.0".equals(version)) {
            this.strategy = new AlipayV1Adapter(...);
        } else {
            this.strategy = new AlipayV2Adapter(...);
        }
    }
    
    @Override
    public boolean pay(double amount) {
        return strategy.pay(amount);
    }
    
    @Override
    public String getStatus() { return "已处理"; }
}

❌ 问题4: 多个不兼容接口混合导致混乱

症状: 系统中混用不同的支付接口,代码难以维护。

根本原因: 缺陷统一的适配策略。

解决方案:

java
// ✅ 使用层次适配器
public abstract class BasePaymentAdapter implements PaymentGateway {
    protected abstract void executePayment(double amount);
    protected abstract String extractStatus();
    
    @Override
    public final boolean pay(double amount) {
        try {
            executePayment(amount);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public final String getStatus() {
        return extractStatus();
    }
}

public class SpecificAlipayAdapter extends BasePaymentAdapter {
    private LegacyPaymentSystem system;
    
    @Override
    protected void executePayment(double amount) {
        system.processPayment(amount);
    }
    
    @Override
    protected String extractStatus() {
        return "已支付";
    }
}

类适配 vs 对象适配对比

方面类适配对象适配
实现方式继承组合
灵活性低 (单一父类)高
多适配不支持支持
性能略好略差
推荐度⭐⭐⭐⭐⭐⭐⭐

最佳实践

✅ 优先对象适配 - 灵活性更好
✅ 隔离第三方库 - 通过适配器屏蔽变化
✅ 单一职责 - 适配器只负责接口转换
✅ 缓存策略 - 高频调用时缓存适配结果
✅ 版本管理 - 支持多版本第三方库
✅ 异常处理 - 完整的错误处理和日志


何时避免

❌ 简单的接口转换可以直接修改源类
❌ 不兼容问题源于设计缺陷,应该重构而非适配
❌ 过度适配导致代码复杂度增加


真实案例

案例1: 支付网关整合

不同支付商 (支付宝、微信、Stripe) 接口完全不同,使用适配器统一为内部接口。

案例2: 日期处理库

java.util.Date 与 java.time.LocalDateTime 接口不兼容,适配器转换。

案例3: 旧系统集成

集成20年前的遗留系统,现代系统与之通信需要适配器转换。

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the 适配器模式 AI skill do?

将一个类的接口转换为客户端期望的另一个接口,解决不兼容问题。

Why use 适配器模式 on TypingMind?

Because you install it once and use it with any model. 适配器模式 is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install 适配器模式 in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/microwind/ai-skills/tree/main/design-patterns/adapter-pattern. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use 适配器模式?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with 适配器模式?

As many as you like. As long as a model supports skills, you can use 适配器模式 with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the 适配器模式 AI skill free?

Yes. It is published on GitHub by microwind under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇