
本文介绍一种基于索引映射与函数引用表的python工厂模式实现,避免硬编码52个分支,利用ascii码差值将字母快速映射为数组下标,实现letterfactory('bold', 'c', 'lower')一键生成lowerc('bold')。
本文介绍一种基于索引映射与函数引用表的python工厂模式实现,避免硬编码52个分支,利用ascii码差值将字母快速映射为数组下标,实现letterfactory('bold', 'c', 'lower')一键生成lowerc('bold')。
在具有多级继承结构的类体系中(如 Letters → A/B/…/Z → UpperA/LowerA/UpperB/LowerB…),手动编写 26×2=52 条条件分支不仅冗余易错,也违背开闭原则。理想方案应满足:零重复声明、类型安全、可扩展、无字符串反射风险。
✅ 推荐方案:基于字母索引的双数组分发表
核心思想是将 'A'–'Z' 映射为 0–25 整数索引,再分别维护两个函数引用列表——UPPER_CLASSES 和 LOWER_CLASSES,通过一次索引即可完成类选择与实例化:
# 假设所有子类已定义(如 UpperA, LowerA 等)
from typing import Callable, Type
class Letters:
# 预构建函数引用列表(按 A-Z 顺序)
UPPER_CLASSES: list[Type] = [UpperA, UpperB, UpperC, /* ..., */ UpperZ]
LOWER_CLASSES: list[Type] = [LowerA, LowerB, LowerC, /* ..., */ LowerZ]
@classmethod
def LetterFactory(cls, font: str, letter: str, lettercase: str) -> object:
if not ('A' <h3>✅ 进阶优化:自动注册 + 类型提示增强</h3><p>为彻底消除手动列表维护,可借助类装饰器或元类实现自动注册(推荐使用 __init_subclass__):</p><pre class="brush:php;toolbar:false;"># 基类统一注册机制
class LetterBase:
_upper_registry: dict[str, type] = {}
_lower_registry: dict[str, type] = {}
def __init_subclass__(cls, letter: str, case: str, **kwargs):
super().__init_subclass__(**kwargs)
if case == 'upper':
LetterBase._upper_registry[letter] = cls
elif case == 'lower':
LetterBase._lower_registry[letter] = cls
# 使用示例(无需修改 LetterFactory)
class UpperA(LetterBase, letter='A', case='upper'):
def __init__(self, font): self.font = font
class LowerA(LetterBase, letter='A', case='lower'):
def __init__(self, font): self.font = font
# 工厂方法升级为字典查找(更清晰且支持任意字母)
@classmethod
def LetterFactory(cls, font: str, letter: str, lettercase: str) -> object:
registry = (
LetterBase._upper_registry if lettercase.lower() == 'upper'
else LetterBase._lower_registry
)
target_class = registry.get(letter.upper())
if not target_class:
raise KeyError(f"No {lettercase} class registered for letter '{letter}'")
return target_class(font)⚠️ 注意事项与最佳实践
- 避免 globals() 反射:globals()[class_name] 易受命名污染、IDE 无法跳转、类型检查失效,且存在安全风险;
- 优先使用 ord() 而非 string.ascii_uppercase.index():前者 O(1),后者 O(n),且无需导入额外模块;
- 添加输入校验:确保 letter 在 A–Z 范围内,lettercase 仅接受预设值,提升健壮性;
- 考虑泛型约束:若所有子类共享接口,可定义 class LetterProtocol(Protocol): ... 并标注返回类型为 LetterProtocol。
该方案将配置逻辑与业务逻辑分离,扩展新字母时只需新增对应子类(自动注册)或追加到数组末尾,完全规避重复代码,兼顾性能、可读性与可维护性。











