抽象类通过模板方法固化变量流骨架,强制子类实现可变环节,统一上下文容器与变量透传,提供钩子扩展点及运行时可观测能力,保障多任务间流程一致性和扩展弹性。

用抽象类实现统一的任务处理变量流,关键不是堆砌功能,而是把“哪些必须一致”和“哪些允许不同”提前划清边界。生产环境里最怕的不是逻辑复杂,是同一套流程在不同任务中悄悄跑偏——比如有的任务漏了幂等校验,有的跳过了日志埋点,有的没走统一的异常兜底。抽象类配合模板方法,就是给这套变量流装上轨道和卡扣。
定义变量流骨架:明确每一步谁负责、谁不可动
变量流不是指一堆字段,而是指任务执行过程中关键状态的生成、传递与转化顺序。比如一个审批类任务,典型变量流是:业务ID → 上下文初始化 → 输入参数校验 → 业务数据加载 → 变量组装(表单/附件/审批人)→ 调用外部系统 → 记录快照 → 返回结果。这个顺序不能由子类随意调整,必须固化在抽象类的 final 方法里。
- 模板方法(如 execute())用 final 修饰,内部按固定顺序调用 protected 方法
- 每个 protected 方法对应变量流中的一个环节,例如 loadBizData()、assembleVariables()
- 其中可变环节声明为 abstract,强制子类实现;通用环节(如记录开始时间、设置traceId)直接在抽象类里写死
变量注入与透传:避免子类各自维护上下文对象
不同任务需要的变量类型和数量不同,但传递方式应统一。不要让每个子类都 new 一个自己的 Context 对象,而是在抽象类中定义标准上下文容器(如 TaskContext),并提供安全的变量存取接口:
- context.set("applicantId", userId) 和 context.get("approvalTemplateCode", String.class) 这类泛型安全方法,由抽象类提供
- 子类只管往里面塞值,不关心序列化、线程隔离或跨阶段传递机制
- 抽象类在模板方法关键节点自动注入公共变量(如 tenantId、env、operator),子类无需重复获取
钩子驱动的变量校验与增强
有些校验或增强动作不是所有任务都需要,但一旦需要就必须在固定位置发生。这时用钩子方法比抽象方法更合适:
- 定义 beforeAssembleVariables() 和 afterSubmitToDingTalk() 这类带默认空实现的 protected 方法
- 比如财务类任务可在 beforeAssembleVariables() 中自动补全预算编号;合同类任务在 afterSubmitToDingTalk() 中触发法务系统回调
- 钩子不参与主流程强约束,但位置确定、调用可控,既不破坏一致性,又保留扩展弹性
运行时变量可见性与调试支持
生产环境出问题,第一反应往往是“当时变量是什么值”。抽象类可以内置轻量级可观测能力:
- 模板方法执行前后自动采集 context.snapshot(),生成结构化快照(含时间戳、线程名、关键变量键值对)
- 提供 logVariables(level, keys...) 方法,子类可按需打印指定变量,避免日志泄露敏感字段
- 所有变量操作(get/set/remove)经过抽象层拦截,便于后续接入审计或动态脱敏










