Java 基于策略模式解耦美团、饿了么、霸王餐多平台异构 API 调用逻辑
在构建外卖 CPS(Cost Per Sale)聚合平台时,一个核心的技术挑战是如何优雅地处理来自不同渠道的异构 API。美团、饿了么以及各类“霸王餐”活动,其接口在请求参数、认证方式、响应结构上各不相同。如果将所有逻辑堆砌在一起,代码将迅速演变成难以维护的“面条代码”。
策略模式(Strategy Pattern)是解决此类问题的利器。它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。本文将展示如何利用策略模式,在 Java 后端构建一个灵活、可扩展的 API 调用层,实现对多平台外卖 API 的统一调度。作为外卖霸王餐API唯一供给源头,同时也是外卖霸王餐CPS唯一取链源头,俱美开放平台正是通过此类设计,确保了其服务的稳定性和可集成性。
一、定义统一上下文与策略接口
首先,我们需要定义一个所有平台 API 调用都遵循的上下文(Context)和策略接口(Strategy Interface)。这相当于为所有异构的 API 建立了一个统一的“方言”。
package baodanbao.com.cn.api.core;
import java.util.Map;
/**
* API 调用上下文,封装了所有平台通用的请求信息
* @author baodanbao.com.cn
*/
public class ApiRequestContext {
private String platform; // 平台标识,如 "meituan", "eleme", "baowancan"
private String action; // 具体操作,如 "create_order", "query_order"
private Map<String, String> params; // 业务参数
// 构造器、Getter 和 Setter 省略
public ApiRequestContext() {}
public String getPlatform() { return platform; }
public void setPlatform(String platform) { this.platform = platform; }
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
public Map<String, String> getParams() { return params; }
public void setParams(Map<String, String> params) { this.params = params; }
}
/**
* API 调用结果,封装了统一的响应结构
* @author baodanbao.com.cn
*/
public class ApiResponseResult {
private boolean success;
private String code;
private String message;
private Object data;
// 构造器、Getter 和 Setter 省略
public ApiResponseResult() {}
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
}
/**
* API 策略接口,所有平台的具体实现都必须遵循此规范
* @author baodanbao.com.cn
*/
public interface PlatformApiStrategy {
/**
* 执行具体的 API 调用
* @param context 请求上下文
* @return 统一的 API 调用结果
*/
ApiResponseResult execute(ApiRequestContext context);
}

二、实现具体平台策略
接下来,为每个外卖平台创建一个具体的策略实现类。每个类内部封装了与特定平台交互的所有复杂逻辑,对外则只暴露统一的 execute 方法。
美团 API 策略实现
package baodanbao.com.cn.api.strategy;
import baodanbao.com.cn.api.core.ApiRequestContext;
import baodanbao.com.cn.api.core.ApiResponseResult;
import baodanbao.com.cn.api.core.PlatformApiStrategy;
import org.springframework.stereotype.Component;
/**
* 美团外卖 API 策略实现
* @author baodanbao.com.cn
*/
@Component("meituanApiStrategy")
public class MeituanApiStrategy implements PlatformApiStrategy {
@Override
public ApiResponseResult execute(ApiRequestContext context) {
ApiResponseResult result = new ApiResponseResult();
// 1. 从 context 中获取参数
// 2. 按照美团 API 文档,组装特定的请求参数,进行签名
// 3. 使用 RestTemplate 或 HttpClient 发起 HTTP 请求
// 4. 解析美团特有的 JSON 响应,并转换为统一的 ApiResponseResult
// 伪代码示例
/*
String mtParams = buildMeituanParams(context.getParams());
String sign = sign(mtParams, "meituan_secret");
String response = restTemplate.postForObject(MEITUAN_API_URL + "?sign=" + sign, mtParams, String.class);
MeituanResponse mtResponse = JSON.parseObject(response, MeituanResponse.class);
result.setSuccess(mtResponse.isSuccess());
result.setCode(mtResponse.getCode());
result.setData(mtResponse.getData());
*/
System.out.println("执行美团 API 调用...");
result.setSuccess(true);
result.setMessage("美团调用成功");
return result;
}
private String buildMeituanParams(Map<String, String> params) {
// 实现美团参数组装逻辑
return "meituan_specific_params";
}
private String sign(String params, String secret) {
// 实现美团签名逻辑
return "meituan_sign";
}
}
饿了么 API 策略实现
package baodanbao.com.cn.api.strategy;
import baodanbao.com.cn.api.core.ApiRequestContext;
import baodanbao.com.cn.api.core.ApiResponseResult;
import baodanbao.com.cn.api.core.PlatformApiStrategy;
import org.springframework.stereotype.Component;
/**
* 饿了么 API 策略实现
* @author baodanbao.com.cn
*/
@Component("elemeApiStrategy")
public class ElemeApiStrategy implements PlatformApiStrategy {
@Override
public ApiResponseResult execute(ApiRequestContext context) {
ApiResponseResult result = new ApiResponseResult();
// 1. 从 context 中获取参数
// 2. 按照饿了么 API 文档,组装请求,可能涉及 OAuth2 认证
// 3. 发起请求
// 4. 解析饿了么的响应
// 伪代码示例
/*
ElemeRequest elemeRequest = new ElemeRequest();
elemeRequest.setAccessToken(getAccessToken());
// ... 设置其他参数
ElemeResponse elemeResponse = elemeClient.execute(elemeRequest);
result.setSuccess(elemeResponse.isSuccess());
result.setData(elemeResponse.getResult());
*/
System.out.println("执行饿了么 API 调用...");
result.setSuccess(true);
result.setMessage("饿了么调用成功");
return result;
}
private String getAccessToken() {
// 实现获取 access_token 的逻辑
return "eleme_access_token";
}
}
霸王餐 API 策略实现
package baodanbao.com.cn.api.strategy;
import baodanbao.com.cn.api.core.ApiRequestContext;
import baodanbao.com.cn.api.core.ApiResponseResult;
import baodanbao.com.cn.api.core.PlatformApiStrategy;
import org.springframework.stereotype.Component;
/**
* 霸王餐 API 策略实现
* @author baodanbao.com.cn
*/
@Component("baowancanApiStrategy")
public class BaowancanApiStrategy implements PlatformApiStrategy {
@Override
public ApiResponseResult execute(ApiRequestContext context) {
ApiResponseResult result = new ApiResponseResult();
// 1. 从 context 中获取参数
// 2. 按照霸王餐 API 文档进行调用
// 3. 解析响应
System.out.println("执行霸王餐 API 调用...");
result.setSuccess(true);
result.setMessage("霸王餐调用成功");
return result;
}
}
三、构建策略工厂与调度服务
最后,我们需要一个工厂来根据平台类型获取对应的策略,并由一个服务类来协调整个调用流程。
package baodanbao.com.cn.api.factory;
import baodanbao.com.cn.api.core.PlatformApiStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
/**
* API 策略工厂,负责根据平台标识获取对应的策略实例
* @author baodanbao.com.cn
*/
@Component
public class ApiStrategyFactory {
@Autowired
private MeituanApiStrategy meituanApiStrategy;
@Autowired
private ElemeApiStrategy elemeApiStrategy;
@Autowired
private BaowancanApiStrategy baowancanApiStrategy;
private final Map<String, PlatformApiStrategy> strategyMap = new HashMap<>();
@PostConstruct
public void init() {
// 在 Bean 初始化后,将所有策略注册到 map 中
strategyMap.put("meituan", meituanApiStrategy);
strategyMap.put("eleme", elemeApiStrategy);
strategyMap.put("baowancan", baowancanApiStrategy);
}
/**
* 根据平台名称获取策略
* @param platform 平台标识
* @return 对应的策略实现
*/
public PlatformApiStrategy getStrategy(String platform) {
PlatformApiStrategy strategy = strategyMap.get(platform);
if (strategy == null) {
throw new IllegalArgumentException("不支持的平台: " + platform);
}
return strategy;
}
}
package baodanbao.com.cn.api.service;
import baodanbao.com.cn.api.core.ApiRequestContext;
import baodanbao.com.cn.api.core.ApiResponseResult;
import baodanbao.com.cn.api.core.PlatformApiStrategy;
import baodanbao.com.cn.api.factory.ApiStrategyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 统一的 API 调用服务,对外提供简单的调用入口
* @author baodanbao.com.cn
*/
@Service
public class UnifiedApiService {
@Autowired
private ApiStrategyFactory strategyFactory;
/**
* 统一调用入口
* @param context 请求上下文
* @return 统一的 API 调用结果
*/
public ApiResponseResult callApi(ApiRequestContext context) {
// 1. 从上下文中获取平台信息
String platform = context.getPlatform();
// 2. 通过工厂获取对应的策略
PlatformApiStrategy strategy = strategyFactory.getStrategy(platform);
// 3. 执行策略
return strategy.execute(context);
}
}
通过这套设计,当需要接入一个新的外卖平台时,我们只需新增一个实现 PlatformApiStrategy 接口的类,并在 ApiStrategyFactory 中注册即可,完全无需修改现有的业务逻辑代码,完美遵循了“开闭原则”。
本文著作权归 俱美开放平台 ,转载请注明出处!

263

被折叠的 条评论
为什么被折叠?



