基于策略模式动态选择不同地区霸王餐API接口的路由实现

基于策略模式动态选择不同地区霸王餐API接口的路由实现

在"吃喝不愁"App的全国化运营中,不同城市或区域(如北京、上海、成都)对接的"霸王餐"营销活动由本地服务商独立提供,其API地址、认证方式、请求参数格式均存在差异。若采用硬编码分支判断,将导致代码臃肿且难以维护。本文通过策略模式(Strategy Pattern) 结合Spring容器管理,实现灵活、可扩展的地区级API路由机制,并提供完整的Java工程示例。

定义统一接口与策略上下文

首先,抽象出所有地区API的共性行为------提交用户参与请求并返回结果:

java 复制代码
package juwatech.cn.strategy;

public interface FreeMealApiStrategy {
    String getRegionCode();
    FreeMealResponse claim(FreeMealRequest request);
}

其中,FreeMealRequestFreeMealResponse 为通用DTO:

java 复制代码
package juwatech.cn.dto;

public class FreeMealRequest {
    private Long userId;
    private String activityId;
    private String cityCode;
    // getters/setters omitted
}

public class FreeMealResponse {
    private boolean success;
    private String message;
    private String couponCode;
    // getters/setters omitted
}

策略上下文负责根据地区码动态选择具体实现:

java 复制代码
package juwatech.cn.strategy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class FreeMealApiRouter {

    private final Map<String, FreeMealApiStrategy> strategyMap = new ConcurrentHashMap<>();

    @Autowired
    public FreeMealApiRouter(List<FreeMealtApiStrategy> strategies) {
        for (FreeMealApiStrategy strategy : strategies) {
            strategyMap.put(strategy.getRegionCode(), strategy);
        }
    }

    public FreeMealResponse route(FreeMealRequest request) {
        String region = request.getCityCode().substring(0, 2); // 如"10"代表北京
        FreeMealApiStrategy strategy = strategyMap.get(region);
        if (strategy == null) {
            throw new IllegalArgumentException("Unsupported region: " + region);
        }
        return strategy.claim(request);
    }
}

实现各地区具体策略

以北京(BJ)和成都(CD)为例,分别实现策略类:

java 复制代码
package juwatech.cn.strategy.impl;

import juwatech.cn.dto.FreeMealRequest;
import juwatech.cn.dto.FreeMealResponse;
import juwatech.cn.strategy.FreeMealApiStrategy;
import org.springframework.stereotype.Component;

@Component
public class BeijingFreeMealStrategy implements FreeMealApiStrategy {

    @Override
    public String getRegionCode() {
        return "10"; // 北京区号前缀
    }

    @Override
    public FreeMealResponse claim(FreeMealRequest request) {
        // 调用北京专属API:https://bj-promo.eat.com/api/v1/free-meal
        // 此处可集成Feign或RestTemplate
        FreeMealResponse response = new FreeMealResponse();
        response.setSuccess(true);
        response.setMessage("Beijing free meal claimed");
        response.setCouponCode("BJ2025" + request.getUserId());
        return response;
    }
}
java 复制代码
package juwatech.cn.strategy.impl;

import juwatech.cn.dto.FreeMealRequest;
import juwatech.cn.dto.FreeMealResponse;
import juwatech.cn.strategy.FreeMealApiStrategy;
import org.springframework.stereotype.Component;

@Component
public class ChengduFreeMealStrategy implements FreeMealApiStrategy {

    @Override
    public String getRegionCode() {
        return "28"; // 成都区号前缀
    }

    @Override
    public FreeMealResponse claim(FreeMealRequest request) {
        // 调用成都专属API:https://cd-deals.eat.com/open/free
        FreeMealResponse response = new FreeMealResponse();
        response.setSuccess(true);
        response.setMessage("Chengdu free meal issued");
        response.setCouponCode("CD2025" + request.getUserId());
        return response;
    }
}

每个策略类通过@Component自动注册到Spring容器,FreeMealApiRouter在初始化时通过构造注入收集所有实现。

业务服务调用路由

在订单或营销服务中直接使用路由器:

java 复制代码
package juwatech.cn.service;

import juwatech.cn.dto.FreeMealRequest;
import juwatech.cn.dto.FreeMealResponse;
import juwatech.cn.strategy.FreeMealApiRouter;
import org.springframework.stereotype.Service;

@Service
public class FreeMealClaimService {

    private final FreeMealApiRouter router;

    public FreeMealClaimService(FreeMealApiRouter router) {
        this.router = router;
    }

    public FreeMealResponse handleClaim(Long userId, String activityId, String cityCode) {
        FreeMealRequest request = new FreeMealRequest();
        request.setUserId(userId);
        request.setActivityId(activityId);
        request.setCityCode(cityCode);

        return router.route(request);
    }
}

支持动态扩展与配置化

若未来新增城市(如深圳),只需新增一个ShenzhenFreeMealStrategy实现类并标注@Component,无需修改路由逻辑。若需从配置中心加载地区映射,可将regionCode改为读取@Value或Nacos配置,进一步解耦。

此外,可结合工厂模式或注解驱动(如自定义@Region("30"))增强灵活性,但策略模式已满足当前核心需求:开闭原则 (对扩展开放,对修改关闭)与单一职责(每个地区逻辑独立)。

本文著作权归吃喝不愁app开发者团队,转载请注明出处!

相关推荐
意法半导体STM3214 天前
【官方原创】如何为STM32CubeMX2配置Visual Studio Code配置方案
vscode·stm32·单片机·嵌入式硬件·策略模式·stm32cubemx·嵌入式开发
山东点狮信息科技有限公司15 天前
企业级 MES 制造执行系统架构设计与实践
spring cloud·性能优化·系统架构·策略模式·点狮
zzqssliu15 天前
基于策略模式与责任链的代购商品多源采集架构实战
架构·策略模式
mxpan16 天前
macOS 13+ 上使用 macFUSE + NTFS-3G 读写 NTFS 移动硬盘技术说明
macos·策略模式
折哥的程序人生 · 物流技术专研16 天前
Java 23 种设计模式:从踩坑到精通 | 番外:编排器+策略模式在多平台电子面单中的实战(含性能压测)
设计模式·策略模式·代码重构·java设计模式·编排器·电子面单·从踩坑到精通
忧云17 天前
2026年最新 Cursor 国内使用 DeepSeek API等各模型使用完整教程
ai编程·策略模式·cursor·byok·cursor使用国内大模型
AIex-YH17 天前
三域贯通11/12:生物制造的“死亡之谷“,CDMO 是桥还是船?
运维·制造·策略模式
回忆2012初秋18 天前
【Nginx】原理、配置与运维实战(2)
运维·nginx·策略模式
怎么没有名字注册了啊18 天前
macOS 基于 CSDN GitCode + Homebrew Tap 发布 Qt .app 二进制程序通用教程(homebrew 安装自己的软件)
策略模式·homebrew·formula·ruhy
坏小虎19 天前
macOS 安装 Ghostty 终端完整教程:环境、依赖与美化配置
macos·策略模式