如何为需实例化的类实现依赖倒置与接口隔离原则?
解决Clean Architecture中依赖倒置的Python实现方案
核心思路是通过依赖注入+工厂模式,把具体类的实例化逻辑从业务代码(main)中彻底剥离,让main只依赖抽象接口,完全不感知具体实现类的存在,完美契合Clean Architecture和依赖倒置原则的要求。
1. 分层拆分模块
先按Clean Architecture的分层逻辑拆分代码结构:
- 抽象层:定义业务逻辑依赖的接口
- 基础设施层:实现具体功能(比如API调用)
- 工厂层:负责实例化具体类,作为抽象层和实现层的中间桥梁
- 业务逻辑层(main):只依赖抽象接口和工厂
2. 代码实现细节
2.1 抽象接口定义(业务规则层)
创建abstractions/stock_readers.py,用Python的抽象基类(ABC)定义标准接口:
from abc import ABC, abstractmethod from typing import Optional class StockPriceReader(ABC): @abstractmethod def get_price(self, stock_symbol: str) -> Optional[float]: """获取指定股票价格,返回None表示获取失败""" pass
2.2 具体实现类(基础设施层)
创建infrastructure/tick_reader.py,实现抽象接口,包含API凭证等内部细节:
from abstractions.stock_readers import StockPriceReader import requests class TickReaderConcrete(StockPriceReader): def __init__(self, api_key: str): self.api_key = api_key self.base_url = "https://api.example-stock-data.com/v1/price" def get_price(self, stock_symbol: str) -> Optional[float]: try: response = requests.get( self.base_url, params={"symbol": stock_symbol, "apikey": self.api_key} ) response.raise_for_status() return response.json().get("price") except requests.exceptions.RequestException: return None
2.3 工厂函数(依赖注入桥梁)
创建factories/stock_reader_factory.py,负责读取配置并实例化具体类,把实例化逻辑从main中抽离:
from abstractions.stock_readers import StockPriceReader from infrastructure.tick_reader import TickReaderConcrete import os def create_stock_price_reader() -> StockPriceReader: # 从环境变量读取API凭证,避免硬编码 api_key = os.getenv("STOCK_API_KEY") if not api_key: raise ValueError("请配置STOCK_API_KEY环境变量") return TickReaderConcrete(api_key=api_key)
2.4 业务逻辑(main模块)
main.py里只依赖抽象接口和工厂函数,完全不知道TickReaderConcrete的存在:
from abstractions.stock_readers import StockPriceReader from factories.stock_reader_factory import create_stock_price_reader def main(): # 通过工厂获取接口实例,无需关心具体实现 reader: StockPriceReader = create_stock_price_reader() stock_symbol = input("请输入股票代码:") price = reader.get_price(stock_symbol) if price: print(f"{stock_symbol} 当前价格:{price:.2f}") else: print(f"无法获取{stock_symbol}的价格数据") if __name__ == "__main__": main()
3. 为什么符合要求?
- 依赖倒置原则:main(高层模块)依赖抽象接口,具体实现类(低层模块)也依赖同一个抽象,彻底打破了高层依赖低层的传统关系。
- Clean Architecture分层:抽象接口属于内层业务规则,具体实现属于外层基础设施,工厂作为中间层连接内外,符合内层不依赖外层的核心规则。
- 可扩展性:如果后续要替换数据源(比如换API、读本地文件),只需要新增一个
StockPriceReader的实现类,修改工厂函数的返回逻辑即可,main模块完全不用动。
内容的提问来源于stack exchange,提问作者Della
相关产品推荐
相关产品推荐

