依赖注入模式 python
一、核心设计模式:依赖注入模式(Dependency Injection, DI)
这段代码的核心是依赖注入模式(属于控制反转 IoC 的一种实现方式),同时结合了「插件模式(Plugin Pattern)」的基础框架,是工业级插件化系统中最常用的设计组合。
1. 先明确核心模式的定义
- 依赖注入(DI):核心思想是「组件不自行创建依赖对象,而是由外部容器 / 管理器将依赖的实例注入到组件中」,避免组件与依赖硬耦合,提升灵活性和可维护性。
- 插件模式:通过定义统一的插件基类(
Plugin),让不同功能的插件遵循相同规范,由管理器统一加载、初始化和管理,实现功能的可插拔扩展。
二、代码逐行解析(模式特征拆解)
先补充完整代码上下文(便于理解),再分析核心逻辑:
from typing import ClassVar, List, Dict
from pydantic import BaseModel
class Plugin(BaseModel):
# 插件模式:定义插件的通用元信息(唯一标识、依赖声明)
name: ClassVar[str] # 每个插件的唯一标识(插件ID)
depends: ClassVar[List[str]] = None # 当前插件依赖的其他插件名称列表
# 内部属性:存储注入的依赖插件实例(补充缺失的初始化)
_bounds_: Dict[str, "Plugin"] = {}
def setup(self, manager):
# 依赖注入核心逻辑:由manager(外部管理器)注入依赖实例
for k, p in manager.plugins.items(): # 遍历管理器中已加载的所有插件
if k in self.depends: # 匹配当前插件声明的依赖
self._bounds_[k] = p # 将依赖插件实例注入到当前插件的_bounds_中
关键模式特征:
| 代码片段 | 模式特征 | 作用 |
|---|---|---|
name: ClassVar[str] + depends: ClassVar[List[str]] |
插件模式基础 | 定义插件的通用元信息:name 是插件唯一标识,depends 声明当前插件依赖的其他插件名称,是依赖注入的「声明式配置」 |
setup(self, manager) |
依赖注入的「注入入口」 | manager 是外部插件管理器(依赖容器),插件不主动查找依赖,而是通过 setup 方法接收管理器传入的依赖实例 |
manager.plugins.items() |
依赖容器的角色 | manager 作为全局插件容器,持有所有已加载的插件实例,是依赖的「提供者」 |
self._bounds_[k] = p |
依赖注入的核心动作 | 将管理器中匹配的依赖插件实例(p)注入到当前插件的私有属性(_bounds_)中,当前插件后续可直接通过 _bounds_ 使用依赖,而非自行创建 |
三、该模式的核心价值(为什么这么设计)
1. 解决的核心问题
- 避免硬耦合:如果插件自行创建依赖(比如
self.dep = OtherPlugin()),会导致插件与依赖强绑定,一旦依赖插件的初始化逻辑变化,所有使用它的插件都要修改; - 统一管理依赖:由
manager统一加载、初始化所有插件,再注入到需要的插件中,保证依赖实例的唯一性和一致性(比如多个插件依赖同一个EventBus插件,能拿到同一个单例); - 插件解耦:插件只需声明「我需要什么依赖」(
depends),无需关心「依赖从哪来、怎么创建」,符合「单一职责原则」。
2. 插件模式 + 依赖注入的典型场景
这段代码是「插件化系统」的标准设计,常见于:
- 机器人控制系统(如你之前关注的 KUKA 控制柜插件化扩展);
- 工业软件的功能扩展(如 MES 系统的插件化模块);
- 框架级工具(如 FastAPI/Flask 的插件系统、数据处理流水线的插件化节点)。
四、补充:与其他模式的区别(避免混淆)
| 易混淆模式 | 核心区别 |
|---|---|
| 工厂模式 | 工厂模式是「创建对象」,依赖注入是「传递已创建的对象」;工厂模式解决「怎么创建」,DI 解决「怎么传递」 |
| 单例模式 | 单例模式保证「对象唯一」,DI 可结合单例(比如管理器中存储单例插件,注入给所有依赖者),但 DI 核心是「依赖传递」,和单例无必然关联 |
| 策略模式 | 策略模式是「替换算法 / 逻辑」,DI 是「解耦依赖」,策略模式可通过 DI 注入不同策略实现类 |
总结
- 核心模式:依赖注入(DI)模式(控制反转 IoC 的实现),同时基于「插件模式」构建基础框架;
- 核心逻辑:插件通过
depends声明依赖 → 外部管理器(manager)持有所有插件实例 →setup方法将匹配的依赖实例注入到当前插件中; - 核心价值:解耦插件与依赖的硬关联,统一管理依赖生命周期,提升插件化系统的灵活性和可维护性;
- 典型场景:插件化架构的系统(如工业控制软件、框架扩展、模块化工具)。
本文来自博客园,作者:limingqi,转载请注明原文链接:https://www.cnblogs.com/limingqi/p/19733766
浙公网安备 33010602011771号