项目里接了多个第三方 SDK 后,如何使用适配器模式+策略模式优化?(Adapter + Strategy)

文章目录

一、问题

当一个系统需要同时接入多个第三方 SDK,而这些 SDK:

能力相似(功能重合)

接口不一致(方法、参数、返回值都不同)

未来还可能继续扩展

如果在业务层直接使用它们,代码通常会变成这样

java 复制代码
if (type == A) {
    // 调 A 的 SDK
} else if (type == B) {
    // 调 B 的 SDK
}

这是一种糟糕的处理方法,每次随着新增一种SDK 都需要去调整对应的if else 代码 导致大量的嵌套循环。

本文将以实际的例子 去讲解 如何使用适配器模式+ 策略者模式

去优化如此冗长的代码。

将以spring ai 引入 aiyun dashScope 的SDK

以及 引入 openAi SDK为例子 去讲解。

二、先解决第一个问题:接口不统一(Adapter)

目标

让业务层只面对一种"能力接口",而不是多个 SDK。

做法

定义一个统一的适配器接口,抽象出业务真正关心的能力:

java 复制代码
public interface AIModelAdapter {

    String getModelId();

    boolean isEnabled();

    String chat(List<Map<String, String>> messages);

    Flux<String> stream(List<Map<String, String>> messages);

    float[] embed(String text);
}

各个 SDK 各自实现适配器

java 复制代码
public class AliyunAdapter implements AIModelAdapter {
    @Override
    public String chat(...) {
        // 阿里云 SDK 调用细节
    }
}
java 复制代码
public class OpenAIAdapter implements AIModelAdapter {
    @Override
    public String chat(...) {
        // OpenAI SDK 调用细节
    }
}

最终实现:

屏蔽 SDK 差异

统一调用方式

新增 SDK 只需新增 Adapter

业务代码不再直接依赖第三方库

三、第二个问题:Adapter 多了,用哪个?(Strategy)

Adapter 解决了"怎么用 SDK",但没解决"用哪一个"。

如果继续在业务层写判断:

java 复制代码
if (modelId.equals("aliyun")) {
    return aliyunAdapter;
}

本质上还是 if-else,只是换了个地方。

四、把"选择逻辑"集中管理(Strategy Router)

核心原则

选择逻辑必须集中,不能散落在业务代码中。

策略仓库:集中管理所有 Adapter

java 复制代码
public class ModelRegistry {

    private final Map<String, AIModelAdapter> adapters = new HashMap<>();

    public Optional<AIModelAdapter> get(String modelId) {
        return Optional.ofNullable(adapters.get(modelId));
    }

     /**
     * 注册模型适配器
     */
    public void register(AIModelAdapter adapter) {
        adapters.put(adapter.getModelId(), adapter);
        log.info("Registered AI model adapter: {} ({}), enabled: {}", 
                adapter.getModelName(), adapter.getModelId(), adapter.isEnabled());
    }
}

策略路由器:只负责"选哪一个"

java 复制代码
public class ModelRouter {

    ModelRegistry

    public AIModelAdapter route(Long userId) {

			//	ModelRegistry.get()
			//	根据user的选择 从 ModelRegistry 的map中返回可用的模型 adapter
        return selectedAdapter;
    }
}

五、最终调用方式

业务层最终只剩下这两行:

java 复制代码
AIModelAdapter adapter = modelRouter.route(userId);
adapter.chat(messages);

六、这种组合在哪些业务场景特别常见?

支付渠道(支付宝 / 微信 / 银联)

短信服务(多云厂商)

对象存储(OSS / S3 / MinIO)

风控规则 / 排序策略

AI 模型 / 算法切换

只要你看到:

"可能还会再接一家"

"需要按条件选择实现"

这套结构几乎一定用得上。

七、更多的源码:Spring Cache:如何把 Redis / Caffeine / Ehcache 适配成同一套 Cache API

适配器接口:org.springframework.cache.Cache

这是真正的核心接口(简化后):

java 复制代码
public interface Cache {

    String getName();

    Object getNativeCache();

    ValueWrapper get(Object key);

    void put(Object key, Object value);

    void evict(Object key);

    void clear();
}

具体适配器:Redis / Caffeine / Ehcache
Redis 的适配器(简化结构)

java 复制代码
public class RedisCache implements Cache {

    private final RedisOperations redisOperations;

    @Override
    public ValueWrapper get(Object key) {
        Object value = redisOperations.opsForValue().get(key);
        return (value != null ? () -> value : null);
    }

    @Override
    public void put(Object key, Object value) {
        redisOperations.opsForValue().set(key, value);
    }
}

Caffeine 的适配器(简化)

java 复制代码
public class CaffeineCache implements Cache {

    private final com.github.benmanes.caffeine.cache.Cache<Object, Object> cache;

    @Override
    public ValueWrapper get(Object key) {
        Object value = cache.getIfPresent(key);
        return (value != null ? () -> value : null);
    }

    @Override
    public void put(Object key, Object value) {
        cache.put(key, value);
    }
}

你可以清楚看到:

Redis 用的是 RedisOperations

Caffeine 用的是 cache.getIfPresent

但对外暴露的永远是 Cache 接口

相关推荐
m0_5873830038 分钟前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
·云扬·1 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
代码不停2 小时前
自动化测试(java)
java·开发语言·selenium·自动化
鬼手点金4 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
paopaokaka_luck5 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
Wang's Blog5 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo
Wang's Blog5 小时前
Java 项目实战: 交友项目 - Dubbo 入门引导
java·dubbo·交友
蜗牛互联网6 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
SL_staff6 小时前
当规则引擎开始‘懂业务’:JVS-Rules金融风控四大原生能力拆解
java·python·全栈
Shaoshing6 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分