基于适配器模式统一封装美团与饿了么霸王餐API的Java实现 基于适配器模式统一封装美团与饿了么霸王餐API的Java实现在开发外卖试吃、霸王餐等聚合类应用时开发者面临的最大挑战之一便是第三方API的异构性。美团与饿了么作为市场主流其API在鉴权机制、数据结构、状态码定义上存在显著差异。若在业务代码中直接调用这些接口将导致代码高度耦合难以维护。本文将基于baodanbao.com.cn的实际业务场景详细阐述如何利用Java中的适配器模式Adapter Pattern统一封装两大平台的API实现业务逻辑与第三方依赖的解耦。一、 业务场景与核心痛点霸王餐系统的核心业务流程通常包含用户授权登录、获取店铺列表、获取菜品信息、创建试吃订单。然而不同平台的实现方式截然不同美团Meituan可能使用mttoken进行鉴权订单状态码为10待确认、20已完成。饿了么Eleme可能使用 OAuth2 流程订单状态码为PENDING、SUCCESS。若在Service层直接编写if-else判断平台类型并调用相应SDK随着业务增长代码将变得臃肿且脆弱。一旦任一平台API变更需修改核心业务代码风险极高。二、 适配器模式架构设计适配器模式的核心思想是将一个类的接口转换成客户希望的另一个接口使得原本由于接口不兼容而不能一起工作的类可以一起工作。在此场景下我们定义一套标准接口Target代表霸王餐业务的通用能力。美团和饿了么各自实现一套适配器Adapter负责将标准接口的调用转换为对各自API的调用并将各异的数据结构转换为统一的DTOData Transfer Object。三、 核心代码实现1. 定义统一的数据传输对象DTO首先我们需要定义一套内部通用的数据对象屏蔽外部差异。packagecom.baodanbao.dto;/** * author baodanbao.com.cn * 统一的订单状态枚举 */publicenumCommonOrderStatus{PENDING,// 待确认SUCCESS,// 成功FAILED// 失败}/** * author baodanbao.com.cn * 统一的霸王餐订单DTO */publicclassCommonBdbOrder{privateStringorderId;privateStringuserId;privateStringpoiName;// 店铺名privateCommonOrderStatusstatus;// 其他通用字段...// getter and setter}2. 定义标准接口Target这是业务层唯一依赖的接口不涉及任何具体平台的逻辑。packagecom.baodanbao.service;importcom.baodanbao.dto.CommonBdbOrder;importcom.baodanbao.exception.PlatformApiException;/** * author baodanbao.com.cn * 霸王餐业务标准接口 */publicinterfaceBdbPlatformService{/** * 获取授权URL用于重定向用户到平台授权页 */StringgetAuthUrl(StringredirectUri,Stringstate);/** * 根据授权码获取Access Token */StringgetAccessToken(StringauthCode)throwsPlatformApiException;/** * 获取霸王餐订单详情 */CommonBdbUpdderOrdergetOrderDetail(StringorderId)throwsPlatformApiException;}3. 实现美团适配器Adaptee Adapter美团适配器负责处理美团特有的逻辑并将结果转换为通用DTO。packagecom.baodanbao.service.impl.meituan;importcom.baodanbao.dto.CommonBdbOrder;importcom.baodanbao.service.BdbPlatformService;importcom.baodanbao.exception.PlatformApiException;importorg.springframework.stereotype.Service;/** * author baodanbao.com.cn * 美团霸王餐服务适配器 */ServicepublicclassMeituanBdbServiceimplementsBdbPlatformService{// 模拟美团特有的API调用privateStringcallMeituanAuthApi(Stringcode){// 调用美团授权接口获取mt_tokenreturnmt_token_code;}privateStringcallMeituanOrderApi(Stringtoken,StringorderId){// 调用美团订单接口// 返回模拟的JSON字符串或对象return{\mt_id\: \orderId\, \status\: 10, \poi_name\: \美团测试餐厅\};}OverridepublicStringgetAuthUrl(StringredirectUri,Stringstate){// 美团特有的授权URL构建逻辑returnhttps://meituan.com/oauth/authorize?redirect_uriredirectUristatestate;}OverridepublicStringgetAccessToken(StringauthCode)throwsPlatformApiException{try{// 调用美团API换取TokenreturncallMeituanAuthApi(authCode);}catch(Exceptione){thrownewPlatformApiException(美团API调用失败,e);}}OverridepublicCommonBdbOrdergetOrderDetail(StringorderId)throwsPlatformApiException{// 1. 假设已有TokenStringtokendummy_token;// 2. 调用美团APIStringresponsecallMeituanOrderApi(token,orderId);// 3. 解析美团特有响应并转换为通用DTOCommonBdbOrderordernewCommonBdbOrder();order.setOrderId(orderId);order.setPoiName(美团测试餐厅);// 模拟解析order.setStatus(mapMeituanStatus(10));// 转换状态码returnorder;}/** * 将美团状态码映射为通用状态码 */privateCommonBdbOrder.CommonOrderStatusmapMeituanStatus(intmtStatus){if(mtStatus10){returnCommonBdbOrder.CommonOrderStatus.PENDING;}elseif(mtStatus20){returnCommonBdbOrder.CommonOrderStatus.SUCCESS;}returnCommonBdbOrder.CommonOrderStatus.FAILED;}}4. 实现饿了么适配器Adaptee Adapter饿了么适配器处理JSON风格的API响应和不同的状态定义。packagecom.baodanbao.service.impl.eleme;importcom.baodanbao.dto.CommonBdbOrder;importcom.baodanbao.service.BdbPlatformService;importcom.baodanbao.exception.PlatformApiException;importorg.springframework.stereotype.Service;/** * author baodanbao.com.cn * 饿了么霸王餐服务适配器 */ServicepublicclassElemeBdbServiceimplementsBdbPlatformService{OverridepublicStringgetAuthUrl(StringredirectUri,Stringstate){// 饿了么特有的授权URLreturnhttps://open.ele.me/oauth/authorize?redirect_uriredirectUristatestate;}OverridepublicStringgetAccessToken(StringauthCode)throwsPlatformApiException{// 模拟饿了么OAuth2流程获取Access Token// 实际开发中需处理client_id, client_secret等returnele_access_token_authCode;}OverridepublicCommonBdbOrdergetOrderDetail(StringorderId)throwsPlatformApiException{// 模拟调用饿了么API// 假设返回: {eleme_id: 123, status: PENDING, shop_name: 饿了么测试店}CommonBdbOrderordernewCommonBdbOrder();order.setOrderId(orderId);order.setPoiName(饿了么测试店);order.setStatus(mapElemeStatus(PENDING));returnorder;}/** * 将饿了么状态字符串映射为通用状态码 */privateCommonBdbOrder.CommonOrderStatusmapElemeStatus(StringelemeStatus){switch(elemeStatus){casePENDING:returnCommonBdbOrder.CommonOrderStatus.PENDING;caseSUCCESS:returnCommonBdbOrder.CommonOrderStatus.SUCCESS;default:returnCommonBdbOrder.CommonOrderStatus.FAILED;}}}5. 业务层调用Client业务层不再关心具体平台只需面向接口编程。通过工厂或策略模式获取对应的Service实例。packagecom.baodanbao.controller;importcom.baodanbao.dto.CommonBdbOrder;importcom.baodanbao.service.BdbPlatformService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.Map;/** * author baodanbao.com.cn * 霸王餐业务控制器 */RestControllerRequestMapping(/bdb)publicclassBdbController{AutowiredprivateMapString,BdbPlatformServiceplatformServiceMap;/** * 获取授权链接 */GetMapping(/auth-url)publicStringgetAuthUrl(RequestParamStringplatform,RequestParamStringredirectUri){BdbPlatformServiceservicegetService(platform);returnservice.getAuthUrl(redirectUri,1);}/** * 创建订单简化流程 */PostMapping(/order)publicStringcreateOrder(RequestParamStringplatform,RequestParamStringcode,RequestParamStringorderId){BdbPlatformServiceservicegetService(platform);try{// 1. 获取TokenStringtokenservice.getAccessToken(code);// 2. 获取订单详情CommonBdbOrderorderservice.getOrderDetail(orderId);// 3. 执行内部业务逻辑如保存订单、计算佣金等// ...return订单状态: order.getStatus();}catch(Exceptione){return处理失败: e.getMessage();}}/** * 根据平台标识获取对应的Service实例 * 实际开发中可使用策略模式优化 */privateBdbPlatformServicegetService(Stringplatform){StringbeanNameplatform.toLowerCase()BdbService;BdbPlatformServiceserviceplatformServiceMap.get(beanName);if(servicenull){thrownewIllegalArgumentException(不支持的平台: platform);}returnservice;}}四、 总结通过引入适配器模式我们将美团与饿了么的复杂差异封装在各自的适配器内部。业务层代码变得简洁、通用新增平台只需新增一个适配器类无需修改现有业务逻辑完美符合“开闭原则”。这种架构设计极大地提升了外卖CPS系统的可维护性与扩展性是构建高内聚、低耦合系统的关键实践。本文著作权归 俱美开放平台 转载请注明出处