项目里接了多个第三方 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 接口

相关推荐
qq_2975746711 小时前
【实战】POI 实现 Excel 多级表头导出(含合并单元格完整方案)
java·spring boot·后端·excel
星辰_mya11 小时前
Elasticsearch线上问题之慢查询
java·开发语言·jvm
南极星100511 小时前
我的创作纪念日--128天
java·python·opencv·职场和发展
郝学胜-神的一滴11 小时前
超越Spring的Summer(一): PackageScanner 类实现原理详解
java·服务器·开发语言·后端·spring·软件构建
摇滚侠11 小时前
Java,举例说明,函数式接口,函数式接口实现类,通过匿名内部类实现函数式接口,通过 Lambda 表达式实现函数式接口,演变的过程
java·开发语言·python
打工的小王11 小时前
java并发编程(七)ReentrantReadWriteLock
java·开发语言
lang2015092811 小时前
Java并发革命:JSR-133深度解析
java·开发语言
abluckyboy11 小时前
基于 Java Socket 实现多人聊天室系统(附完整源码)
java·开发语言
Re.不晚11 小时前
JAVA进阶之路——数据结构之线性表(顺序表、链表)
java·数据结构·链表
毅炼11 小时前
Java 基础常见问题总结(3)
java·开发语言