本文介绍如何在面向对象重构中优雅处理多分支线性流程——通过组合策略模式、责任链思想与条件驱动执行,避免子类重复定义执行顺序,消除硬编码调用链,提升可维护性与扩展性。
本文介绍如何在面向对象重构中优雅处理多分支线性流程——通过组合策略模式、责任链思想与条件驱动执行,避免子类重复定义执行顺序,消除硬编码调用链,提升可维护性与扩展性。
在将传统过程式算法迁移到面向对象设计时,一个常见挑战是:多个业务场景共享相似但不完全一致的执行流程(如初始化 → 数据加载 → 变换 → 输出),其中某些步骤依条件跳过,且不同场景的步骤顺序与组合存在差异。若采用“抽象基类 + 子类重写 execute()”的朴素方案,极易导致大量重复的调用序列逻辑(如每个子类都写 step1(); if (cond) step2(); step3(); ...),违背 DRY 原则,也难以应对后续流程变更。
更优解是分离“流程结构”与“步骤行为”,推荐以下三层架构:
1. 步骤抽象化:定义可插拔的操作单元
将每个函数(如 initializeVariables()、addDataFromDraft())封装为独立的、无状态的策略类或函数式接口实现:
@FunctionalInterface
interface ProcessingStep {
void execute(Context context);
}
// 示例实现
class InitializeVariablesStep implements ProcessingStep {
public void execute(Context context) {
context.setVariables(new HashMap<>());
}
}
class AddDataFromDraftStep implements ProcessingStep {
public void execute(Context context) {
if (context.getDraft() != null) {
context.getData().addAll(context.getDraft().getData());
}
}
}2. 流程动态化:用配置驱动执行序列
不再由类硬编码调用顺序,而是将每种用例建模为一个步骤列表(List
public class PipelineExecutor {
private final List<ProcessingStep> steps;
public PipelineExecutor(List<ProcessingStep> steps) {
this.steps = steps;
}
public void execute(Context context) {
for (ProcessingStep step : steps) {
step.execute(context);
}
}
}
// 按需构建不同流程
PipelineExecutor useCaseA = new PipelineExecutor(Arrays.asList(
new InitializeVariablesStep(),
new SaveTemporaryDataStep(),
new AddDataFromExternalSourceStep(),
new SortDataStep(),
new PrepareOutputStep()
));
PipelineExecutor useCaseB = new PipelineExecutor(Arrays.asList(
new InitializeVariablesStep(),
new SaveTemporaryDataStep(),
new AddDataFromDraftStep(), // 条件步骤,内部自行判断是否执行
new AddDataFromExternalSourceStep(),
new SortDataStep(),
new PrepareOutputStep()
));3. 条件逻辑内聚化:步骤自身负责守卫逻辑
关键改进点:跳过逻辑不应由调度器判断,而应下沉到具体步骤内部。例如 AddDataFromDraftStep 自行检查 context.getDraft() != null,既保持步骤自治,又避免外部重复条件分支:
class AddDataFromDraftStep implements ProcessingStep {
@Override
public void execute(Context context) {
// 守卫逻辑内聚于此——清晰、可测试、可复用
if (context.getDraft() == null) return;
context.getData().addAll(context.getDraft().getData());
}
}注意事项与最佳实践
- ✅ Context 对象需精简设计:仅携带各步骤真正需要的数据(如 Map
state, Draft draft, List data),避免沦为万能容器; - ✅ 步骤应无副作用或明确声明副作用:确保可安全重试、跳过或重排序;
- ⚠️ 避免在步骤中强耦合其他步骤——若某步必须依赖另一步输出,应通过 Context 显式传递,而非直接调用;
- ? 进阶可引入 StepFilter 或注解(如 @EnabledIf("draftAvailable"))实现声明式条件控制;
- ? 单元测试聚焦单个步骤行为,集成测试验证完整 Pipeline 行为,大幅提升可测性。
这种设计将“什么要执行”(配置化流程)与“如何执行”(策略化步骤)彻底解耦,既消除了子类中冗余的 if/else 调用链,又为新增用例、步骤复用、运行时流程切换提供了坚实基础——这才是面向对象对流程复杂性的本质回应。










