简单工厂模式 python
一、核心模式:工厂模式(Factory Pattern)+ 注册表模式(Registry Pattern)
这段代码是简单工厂模式(Simple Factory)的典型实现,同时结合了「注册表模式(Registry Pattern)」(也叫注册器模式),属于设计模式中「创建型模式」的组合应用,核心目标是统一管理对象的创建逻辑,通过 “名称 - 类型” 映射动态创建实例。
1. 核心模式的定义
- 注册表模式:通过一个全局字典(
__ACTIONS__)维护「标识(如 Name)- 类(Action 子类)」的映射关系,实现类的动态注册和查找,是工厂模式的基础; - 简单工厂模式:通过一个统一的入口方法(
from_dict),根据传入的标识(name)从注册表中找到对应类,再创建实例,避免直接使用new/__init__硬编码创建对象。
二、代码补全与逐行解析(模式特征拆解)
先补充完整上下文(修复语法问题 + 补全依赖),再分析核心逻辑:
from typing import Type, Dict, Any
# 定义Action基类(补充上下文)
class Action:
# 注册表核心:存储「Action名称-Action子类」的映射
__ACTIONS__: Dict[str, Type["Action"]] = {}
# 每个Action子类需定义的唯一名称属性
Name: str = ""
@staticmethod
def register(atype: Type["Action"]):
"""注册表模式核心:将Action子类注册到全局字典"""
# 以子类的Name属性为key,类本身为value,存入注册表
Action.__ACTIONS__[atype.Name] = atype
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Action":
"""工厂模式核心:从注册表动态创建实例"""
# 从传入的字典中提取Action名称(修复原代码的name/kwargs未定义问题)
name = data.get("name") # 假设data中包含"name"字段,对应Action的Name
kwargs = {k: v for k, v in data.items() if k != "name"} # 剩余参数作为初始化参数
# 从注册表中找到对应类,动态创建实例
return Action.__ACTIONS__[name](**kwargs)
# 示例:定义Action子类并注册
class MoveAction(Action):
Name = "move" # 定义唯一名称
def __init__(self, x: int, y: int):
self.x = x
self.y = y
# 注册子类到注册表
Action.register(MoveAction)
# 工厂方法创建实例
data = {"name": "move", "x": 10, "y": 20}
action = Action.from_dict(data)
print(isinstance(action, MoveAction)) # 输出:True
关键设计点(模式特征):
| 代码片段 | 模式特征 | 作用 |
|---|---|---|
__ACTIONS__: Dict[str, Type["Action"]] |
注册表核心 | 全局字典作为 “类注册表”,存储所有可创建的 Action 子类,是动态创建的基础; |
@staticmethod register(atype) |
注册表模式 - 注册逻辑 | 将自定义的 Action 子类(如 MoveAction)注册到注册表,无需修改工厂方法即可扩展新类型; |
@classmethod from_dict(data) |
工厂模式 - 创建逻辑 | 统一的实例创建入口:从 data 中提取名称 → 查注册表找对应类 → 动态初始化实例; |
Action.__ACTIONS__[name](** kwargs) |
动态创建核心 | 避免硬编码 if name == "move": return MoveAction(),新增 Action 子类只需注册,无需修改工厂方法; |
三、该模式的核心价值(为什么这么设计)
1. 解决的核心问题
- 避免硬编码创建逻辑:如果不用工厂 + 注册表,创建实例需要写大量
if-elif(如if name=="move": return MoveAction()),新增 Action 子类需修改创建逻辑,违反「开闭原则」; - 统一管理类的创建:所有 Action 实例都通过
from_dict创建,便于统一添加日志、参数校验、异常处理等通用逻辑; - 动态扩展:新增 Action 子类(如
StopAction)只需定义类 + 调用register注册,无需修改原有代码,符合 “对扩展开放、对修改关闭” 的设计原则。
2. 与其他工厂模式的区别(避免混淆)
| 工厂模式类型 | 核心特征 | 你的代码对应关系 |
|---|---|---|
| 简单工厂模式 | 一个工厂方法创建所有类型实例 | from_dict 是唯一的工厂方法,创建所有 Action 子类实例 |
| 工厂方法模式 | 每个产品类型对应一个工厂子类 | 你的代码未用到(更复杂,适合产品层级多的场景) |
| 抽象工厂模式 | 创建一组相关产品 | 你的代码未用到(适合多产品族场景) |
你的代码是「简单工厂模式 + 注册表模式」:注册表解决 “类的动态映射”,简单工厂解决 “统一创建入口”,是工业级代码中最常用的轻量工厂实现。
四、典型适用场景
这种模式广泛用于需要「动态扩展、统一创建」的场景,比如:
- 工业控制软件(如 KUKA 机器人的动作指令:移动、停止、抓取等,新增指令只需注册);
- 配置化实例创建(从 JSON/YAML 配置文件读取参数,动态创建对应类实例);
- 插件化系统(插件的注册和创建,如你之前的 Plugin 体系);
- 序列化 / 反序列化(从字典 / JSON 还原为不同类型的对象)。
五、原代码的小问题(新手避坑)
原代码存在 2 个语法 / 逻辑问题,已在完整代码中修复:
from_dict中name和kwargs未定义:需从data中提取(如name = data["name"]);- 未定义
__ACTIONS__字典:需在 Action 类中初始化这个注册表容器; - 未明确
atype.Name的来源:需保证每个 Action 子类都定义Name类属性。
总结
- 核心模式:简单工厂模式 + 注册表模式(创建型模式组合);
- 核心逻辑:先通过
register将 Action 子类注册到全局注册表(__ACTIONS__),再通过from_dict从注册表中根据名称动态创建实例; - 核心价值:解耦实例创建逻辑与具体类,支持动态扩展,符合开闭原则;
- 典型场景:配置化创建对象、插件注册与实例化、工业控制的指令系统。
本文来自博客园,作者:limingqi,转载请注明原文链接:https://www.cnblogs.com/limingqi/p/19734414
浙公网安备 33010602011771号