模板方法模式在Python中无需抽象类,可用函数参数或钩子方法解耦可变逻辑;若使用abc.ABC和@abstractmethod,须确保子类实现所有抽象方法,否则实例化时报错,且抽象方法不校验返回值与行为。

模板方法模式在Python里不用抽象类也能做,关键在于用函数参数或钩子方法把可变逻辑抽出去,让父类只控制流程顺序。
用 abc.ABC 和 @abstractmethod 定义骨架时要注意什么
很多人以为必须继承 abc.ABC 才算模板方法,其实不是——但如果你用了,就得确保子类真正实现所有 @abstractmethod,否则实例化时直接报 TypeError: Can't instantiate abstract class。
- 抽象方法只校验签名,不校验返回值或行为,所以子类可能返回错误类型却不出错
-
__init__里调用抽象方法会失败,因为此时子类还没完成初始化,应避免在构造中触发钩子 - 想跳过某步?不能靠“空实现”,得额外加
is_enabled类属性或参数控制,否则骨架被强行执行
用普通基类 + 可选钩子方法更灵活
去掉 abc 依赖后,模板逻辑反而更贴近实际项目:有些步骤本就可选,有些默认行为合理,没必要强制重写。
- 把核心步骤设为
def step_one(self): pass,子类按需覆盖,不覆盖就走空逻辑 - 用
if hasattr(self, '_preprocess')或getattr(self, 'skip_validation', False)控制分支 - 钩子名建议带前缀(如
_before_run、_on_failure),避免和业务方法名冲突 - 性能上无差异,但调试时更容易看到“哪步没定义”,而不是卡在抽象类实例化阶段
用函数参数替代继承:适合简单场景
当算法只有 1–2 个可变点,且不想建一堆子类时,直接把函数传进来最轻量。
立即学习“Python免费学习笔记(深入)”;
- 模板方法写成普通函数:
def run_pipeline(validate_func=None, transform_func=None): - 内部用
validate_func(data) if validate_func else lambda x: True做兜底 - 注意闭包变量捕获问题:如果
transform_func引用了外部对象状态,要确认生命周期是否匹配 - 这种写法无法复用中间状态(比如共享缓存字段),纯函数式风格下得靠参数传递或 closure 维护
最容易被忽略的是“骨架变更成本”——一旦上线后要在主流程里插新步骤,所有子类都得同步改,哪怕只是加个日志钩子。所以初期多留一两个预留钩子(如 _on_step_x_start),比后期批量重构强得多。


















