Java 基于策略模式解耦美团、饿了么、霸王餐多平台异构 API 调用逻辑

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 中注册即可,完全无需修改现有的业务逻辑代码,完美遵循了“开闭原则”。

本文著作权归 俱美开放平台 ,转载请注明出处!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值