多API数据获取类的灵活设计:适用何种设计模式?
针对API调用类的设计模式建议
针对你描述的「功能相同但实现不同、部分仅参数有别」的network类场景,以下几种设计模式和实践可以完美适配:
1. 抽象基类 + 工厂模式 + 配置驱动
这是最直接的方案,既能统一接口,又能避免为参数差异的API创建冗余类:
- 先定义抽象基类
BaseNetwork,约定所有network类必须实现的核心方法(比如fetch_data); - 为逻辑/实现不同的API创建独立子类,继承
BaseNetwork并实现自定义逻辑; - 为仅参数差异的API创建一个通用子类,通过构造函数接收差异化参数(如API地址、密钥、超时时间等);
- 用工厂函数或配置列表来批量生成实例,替代返回类名数组的方式。
示例代码:
from abc import ABC, abstractmethod # 抽象基类 class BaseNetwork(ABC): @abstractmethod def fetch_data(self, query_params): """核心方法:获取API数据""" pass # 针对逻辑不同的API的子类 class APINetworkA(BaseNetwork): def fetch_data(self, query_params): # 实现API A特有的请求、解析逻辑 response = self._send_request("https://api.a.com/data", query_params) return self._parse_a_response(response) # 通用子类:适配仅参数差异的API class GenericNetwork(BaseNetwork): def __init__(self, api_url, api_key, timeout=10): self.api_url = api_url self.api_key = api_key self.timeout = timeout def fetch_data(self, query_params): # 通用请求逻辑,使用实例化时传入的参数 headers = {"Authorization": f"Bearer {self.api_key}"} response = self._send_request(self.api_url, query_params, headers, self.timeout) return self._parse_generic_response(response) # 替代get_networks():返回配置或实例列表 def get_network_configs(): return [ # 逻辑不同的API:直接返回类(或实例) APINetworkA(), # 参数不同的API:返回通用类+参数配置 (GenericNetwork, {"api_url": "https://api.x.com/v1", "api_key": "XXX"}), (GenericNetwork, {"api_url": "https://api.y.com/v2", "api_key": "YYY", "timeout": 15}) ] # 加载时的实例化逻辑 def load_networks(): networks = [] for item in get_network_configs(): if isinstance(item, type): networks.append(item()) elif isinstance(item, tuple): cls, kwargs = item networks.append(cls(**kwargs)) return networks
2. 策略模式(适合逻辑拆分更细的场景)
如果不同API的差异主要在请求构造、数据解析等局部逻辑,而非整体流程,可以用策略模式将可变逻辑抽离:
- 定义
RequestStrategy、ParseStrategy等抽象策略类,封装可变逻辑; NetworkClient作为上下文类,持有策略对象,并实现通用流程(如发送请求、错误处理);- 仅参数差异的API复用同一策略类,通过参数初始化策略;逻辑不同的API使用自定义策略类。
示例代码:
from abc import ABC, abstractmethod # 请求构造策略 class RequestStrategy(ABC): @abstractmethod def build_request(self, query_params): pass # 通用请求策略:适配参数差异的API class GenericRequestStrategy(RequestStrategy): def __init__(self, api_url, api_key): self.api_url = api_url self.api_key = api_key def build_request(self, query_params): return { "url": self.api_url, "params": query_params, "headers": {"Authorization": f"Bearer {self.api_key}"} } # 自定义请求策略:适配逻辑不同的API class APIARequestStrategy(RequestStrategy): def build_request(self, query_params): # API A特有的请求构造逻辑 return { "url": "https://api.a.com/data", "params": {"q": query_params["keyword"], "limit": 20}, "headers": {"X-API-Key": "AAA"} } # 上下文类:通用流程 class NetworkClient: def __init__(self, request_strategy): self.request_strategy = request_strategy def fetch_data(self, query_params): request = self.request_strategy.build_request(query_params) response = self._send_http_request(**request) return self._parse_response(response) # 加载逻辑 def get_networks(): return [ NetworkClient(APIARequestStrategy()), NetworkClient(GenericRequestStrategy("https://api.x.com", "XXX")), NetworkClient(GenericRequestStrategy("https://api.y.com", "YYY")) ]
关于生成器与可迭代类的使用
生成器和可迭代类并非核心设计模式,但可以作为优化手段配合上述方案使用:
- 如果API数量较多,不需要一次性创建所有实例,可以把
get_networks()改成生成器,按需生成实例:def get_networks(): yield NetworkClient(APIARequestStrategy()) yield NetworkClient(GenericRequestStrategy("https://api.x.com", "XXX")) yield NetworkClient(GenericRequestStrategy("https://api.y.com", "YYY")) - 可迭代类适合需要自定义遍历逻辑的场景(比如按API类型过滤),但多数情况下生成器足够简洁。
内容的提问来源于stack exchange,提问作者Singleton
相关产品推荐
相关产品推荐

