REST API模板方法模式优化:按逻辑操作而非请求创建类的方案问询
优化REST API封装:策略模式+分组管理方案
你当前用模板方法模式的问题在于,每个API端点都要创建一个子类,50个端点就会产生50个类,既冗余又不利于按逻辑模块维护。推荐用**策略模式(Strategy Pattern)**搭配分组管理,既能让开发者自定义请求/响应逻辑,又能把API调用的核心逻辑集中管控。
核心思路
- 把每个API请求的个性化逻辑(构建URI、请求体、解析响应)抽成独立的请求策略类,同逻辑模块的策略可以归为一组(比如用户相关、订单相关)。
- 保留一个统一的核心服务类,负责HttpClient的初始化、通用调用流程(比如异常处理、超时设置),然后通过注入不同的请求策略来处理具体API。
代码实现示例
1. 定义请求策略接口
这个接口包含请求构建和响应解析的抽象方法,让每个策略实现自己的个性化逻辑:
public interface IApiRequestStrategy<TRequest, TResponse> { string CreateRequestUri(); HttpContent CreateRequestBody(TRequest requestData); Task<TResponse> ParseResponseAsync(HttpResponseMessage response); }
2. 实现统一的API核心服务类
这个类负责集中管理通用调用逻辑,依赖注入具体的策略来处理不同请求:
public class ApiClient { private readonly HttpClient _httpClient; public ApiClient(HttpClient httpClient) { _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } public async Task<TResponse> ExecuteAsync<TRequest, TResponse>( IApiRequestStrategy<TRequest, TResponse> strategy, TRequest requestData) { // 通用调用逻辑:超时、异常处理等都可以在这里集中实现 var uri = strategy.CreateRequestUri(); var requestBody = strategy.CreateRequestBody(requestData); var response = await _httpClient.PostAsync(uri, requestBody); response.EnsureSuccessStatusCode(); return await strategy.ParseResponseAsync(response); } }
3. 按逻辑模块实现具体策略
比如订单模块下的创建订单和查询订单策略,归到订单相关的逻辑组:
// 订单模块:创建订单策略 public class CreateOrderRequestStrategy : IApiRequestStrategy<CreateOrderDto, OrderResultDto> { public string CreateRequestUri() { return "/api/orders/create"; } public HttpContent CreateRequestBody(CreateOrderDto requestData) { return new StringContent(JsonSerializer.Serialize(requestData), Encoding.UTF8, "application/json"); } public async Task<OrderResultDto> ParseResponseAsync(HttpResponseMessage response) { var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<OrderResultDto>(content); } } // 订单模块:查询订单策略 public class GetOrderRequestStrategy : IApiRequestStrategy<GetOrderQuery, OrderDetailDto> { public string CreateRequestUri() { // 可以根据查询参数动态拼接URI return "/api/orders/detail"; } public HttpContent CreateRequestBody(GetOrderQuery requestData) { return new FormUrlEncodedContent(new Dictionary<string, string> { {"orderId", requestData.OrderId.ToString()} }); } public async Task<OrderDetailDto> ParseResponseAsync(HttpResponseMessage response) { var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<OrderDetailDto>(content); } }
4. 使用方式
// 初始化ApiClient(可以通过DI容器注入) var httpClient = Utilities.GetHttpClient(); var apiClient = new ApiClient(httpClient); // 调用创建订单接口 var createOrderStrategy = new CreateOrderRequestStrategy(); var createOrderDto = new CreateOrderDto { /* 填充数据 */ }; var orderResult = await apiClient.ExecuteAsync(createOrderStrategy, createOrderDto); // 调用查询订单接口 var getOrderStrategy = new GetOrderRequestStrategy(); var getOrderQuery = new GetOrderQuery { OrderId = 123 }; var orderDetail = await apiClient.ExecuteAsync(getOrderStrategy, getOrderQuery);
额外优化
如果想进一步减少类数量,还可以把同模块的策略用组合模式封装成一个模块类,比如OrderApiModule,里面包含该模块下所有请求策略的实例,方便统一管理和调用。
这种方案的优势:
- 核心调用逻辑(HttpClient管理、异常处理、状态码校验)集中在
ApiClient,不用重复写。 - 按业务逻辑模块组织策略类,避免类爆炸,维护更清晰。
- 每个策略只负责自己的请求/响应逻辑,符合单一职责原则,也方便扩展新端点。
内容的提问来源于stack exchange,提问作者Sagar
相关产品推荐
相关产品推荐

