You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

REST API模板方法模式优化:按逻辑操作而非请求创建类的方案问询

优化REST API封装:策略模式+分组管理方案

你当前用模板方法模式的问题在于,每个API端点都要创建一个子类,50个端点就会产生50个类,既冗余又不利于按逻辑模块维护。推荐用**策略模式(Strategy Pattern)**搭配分组管理,既能让开发者自定义请求/响应逻辑,又能把API调用的核心逻辑集中管控。

核心思路

  1. 把每个API请求的个性化逻辑(构建URI、请求体、解析响应)抽成独立的请求策略类,同逻辑模块的策略可以归为一组(比如用户相关、订单相关)。
  2. 保留一个统一的核心服务类,负责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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:45:34