基于策略模式动态选择不同地区霸王餐API接口的路由实现
在"吃喝不愁"App的全国化运营中,不同城市或区域(如北京、上海、成都)对接的"霸王餐"营销活动由本地服务商独立提供,其API地址、认证方式、请求参数格式均存在差异。若采用硬编码分支判断,将导致代码臃肿且难以维护。本文通过策略模式(Strategy Pattern) 结合Spring容器管理,实现灵活、可扩展的地区级API路由机制,并提供完整的Java工程示例。
定义统一接口与策略上下文
首先,抽象出所有地区API的共性行为------提交用户参与请求并返回结果:
java
package juwatech.cn.strategy;
public interface FreeMealApiStrategy {
String getRegionCode();
FreeMealResponse claim(FreeMealRequest request);
}
其中,FreeMealRequest 和 FreeMealResponse 为通用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开发者团队,转载请注明出处!