02 - 核心模型设计 🧩

🎯 目标 : 设计流程编排框架的核心数据模型和接口。项目地址:github.com/nemoob/simp...

🤔 模型设计的重要性

一个好的数据模型是框架成功的基石:

  • 📐 清晰的抽象: 将复杂的业务概念转化为简洁的代码模型
  • 🔗 合理的关系: 模型之间的关系要符合业务逻辑
  • 🚀 扩展性: 能够适应未来的需求变化
  • 🎯 易用性: 开发者能够直观地理解和使用

🎨 核心概念分析

📋 Flow(流程)

流程是一系列有序步骤的集合,代表一个完整的业务过程。

特征:

  • 🆔 唯一标识
  • 📝 描述信息
  • 📋 步骤列表
  • ⚙️ 配置参数
  • 📊 元数据信息

🔧 Step(步骤)

步骤是流程中的最小执行单元,代表一个具体的操作。

特征:

  • 🆔 唯一标识
  • 🏷️ 步骤类型
  • ⚙️ 执行配置
  • 🔗 依赖关系
  • 📊 执行状态

📦 Context(上下文)

上下文是步骤间数据传递的载体,维护流程执行过程中的状态。

特征:

  • 📊 数据存储
  • 🔄 数据传递
  • 🌳 层级结构
  • 🔒 线程安全

🏗️ 模型设计

📋 FlowDefinition - 流程定义

java 复制代码
/**
 * 流程定义接口
 * 定义了一个完整流程的基本信息和步骤列表
 */
public interface FlowDefinition {
    
    /**
     * 获取流程唯一标识
     * @return 流程ID
     */
    String getId();
    
    /**
     * 获取流程名称
     * @return 流程名称
     */
    String getName();
    
    /**
     * 获取流程描述
     * @return 流程描述
     */
    String getDescription();
    
    /**
     * 获取流程版本
     * @return 版本号
     */
    String getVersion();
    
    /**
     * 获取步骤列表
     * @return 步骤定义列表
     */
    List<StepDefinition> getSteps();
    
    /**
     * 获取流程配置
     * @return 配置信息
     */
    Map<String, Object> getConfig();
    
    /**
     * 获取元数据
     * @return 元数据信息
     */
    Map<String, Object> getMetadata();
}

🔧 StepDefinition - 步骤定义

java 复制代码
/**
 * 步骤定义接口
 * 定义了流程中单个步骤的基本信息和执行配置
 */
public interface StepDefinition {
    
    /**
     * 获取步骤唯一标识
     * @return 步骤ID
     */
    String getId();
    
    /**
     * 获取步骤名称
     * @return 步骤名称
     */
    String getName();
    
    /**
     * 获取步骤类型
     * @return 步骤类型枚举
     */
    StepType getType();
    
    /**
     * 获取步骤配置
     * @return 配置信息
     */
    Map<String, Object> getConfig();
    
    /**
     * 获取前置条件
     * @return 前置条件表达式
     */
    String getPrecondition();
    
    /**
     * 获取依赖步骤
     * @return 依赖的步骤ID列表
     */
    List<String> getDependencies();
    
    /**
     * 是否可以并行执行
     * @return true表示可以并行执行
     */
    boolean isParallel();
}

🏷️ StepType - 步骤类型枚举

java 复制代码
/**
 * 步骤类型枚举
 * 定义了框架支持的所有步骤类型
 */
public enum StepType {
    
    /**
     * 简单步骤 - 基础的同步执行步骤
     */
    SIMPLE("simple", "简单步骤"),
    
    /**
     * 服务步骤 - 调用Spring Bean的方法
     */
    SERVICE("service", "服务步骤"),
    
    /**
     * 条件步骤 - 基于表达式的条件分支
     */
    CONDITIONAL("conditional", "条件步骤"),
    
    /**
     * 脚本条件步骤 - 基于脚本的条件分支
     */
    SCRIPT_CONDITIONAL("script_conditional", "脚本条件步骤"),
    
    /**
     * 并行步骤 - 并行执行多个子步骤
     */
    PARALLEL("parallel", "并行步骤"),
    
    /**
     * 循环步骤 - 循环执行子步骤
     */
    LOOP("loop", "循环步骤"),
    
    /**
     * 脚本步骤 - 执行动态脚本
     */
    SCRIPT("script", "脚本步骤");
    
    private final String code;
    private final String description;
    
    StepType(String code, String description) {
        this.code = code;
        this.description = description;
    }
    
    public String getCode() {
        return code;
    }
    
    public String getDescription() {
        return description;
    }
    
    /**
     * 根据代码获取步骤类型
     * @param code 类型代码
     * @return 步骤类型
     */
    public static StepType fromCode(String code) {
        for (StepType type : values()) {
            if (type.code.equals(code)) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown step type: " + code);
    }
}

📦 FlowContext - 执行上下文

java 复制代码
/**
 * 流程执行上下文接口
 * 负责在流程执行过程中存储和传递数据
 */
public interface FlowContext {
    
    /**
     * 获取数据
     * @param key 数据键
     * @param <T> 数据类型
     * @return 数据值
     */
    <T> T get(String key);
    
    /**
     * 获取数据,如果不存在则返回默认值
     * @param key 数据键
     * @param defaultValue 默认值
     * @param <T> 数据类型
     * @return 数据值或默认值
     */
    <T> T get(String key, T defaultValue);
    
    /**
     * 存储数据
     * @param key 数据键
     * @param value 数据值
     */
    void put(String key, Object value);
    
    /**
     * 批量存储数据
     * @param data 数据映射
     */
    void putAll(Map<String, Object> data);
    
    /**
     * 移除数据
     * @param key 数据键
     * @return 被移除的数据值
     */
    Object remove(String key);
    
    /**
     * 检查是否包含指定键
     * @param key 数据键
     * @return true表示包含
     */
    boolean containsKey(String key);
    
    /**
     * 获取所有数据
     * @return 数据映射的只读视图
     */
    Map<String, Object> getAll();
    
    /**
     * 获取所有键
     * @return 键的集合
     */
    Set<String> keySet();
    
    /**
     * 清空所有数据
     */
    void clear();
    
    /**
     * 创建子上下文
     * 子上下文可以访问父上下文的数据,但修改不会影响父上下文
     * @return 子上下文
     */
    FlowContext createChild();
    
    /**
     * 获取父上下文
     * @return 父上下文,如果是根上下文则返回null
     */
    FlowContext getParent();
}

🎨 建造者模式实现

🏗️ FlowDefinitionBuilder

java 复制代码
/**
 * 流程定义建造者
 * 提供链式API来构建流程定义
 */
public class FlowDefinitionBuilder {
    
    private String id;
    private String name;
    private String description;
    private String version = "1.0.0";
    private List<StepDefinition> steps = new ArrayList<>();
    private Map<String, Object> config = new HashMap<>();
    private Map<String, Object> metadata = new HashMap<>();
    
    /**
     * 创建建造者实例
     * @param id 流程ID
     * @return 建造者实例
     */
    public static FlowDefinitionBuilder builder(String id) {
        return new FlowDefinitionBuilder().id(id);
    }
    
    /**
     * 设置流程ID
     * @param id 流程ID
     * @return 建造者实例
     */
    public FlowDefinitionBuilder id(String id) {
        this.id = id;
        return this;
    }
    
    /**
     * 设置流程名称
     * @param name 流程名称
     * @return 建造者实例
     */
    public FlowDefinitionBuilder name(String name) {
        this.name = name;
        return this;
    }
    
    /**
     * 设置流程描述
     * @param description 流程描述
     * @return 建造者实例
     */
    public FlowDefinitionBuilder description(String description) {
        this.description = description;
        return this;
    }
    
    /**
     * 设置流程版本
     * @param version 版本号
     * @return 建造者实例
     */
    public FlowDefinitionBuilder version(String version) {
        this.version = version;
        return this;
    }
    
    /**
     * 添加步骤
     * @param step 步骤定义
     * @return 建造者实例
     */
    public FlowDefinitionBuilder addStep(StepDefinition step) {
        this.steps.add(step);
        return this;
    }
    
    /**
     * 批量添加步骤
     * @param steps 步骤列表
     * @return 建造者实例
     */
    public FlowDefinitionBuilder addSteps(List<StepDefinition> steps) {
        this.steps.addAll(steps);
        return this;
    }
    
    /**
     * 添加配置
     * @param key 配置键
     * @param value 配置值
     * @return 建造者实例
     */
    public FlowDefinitionBuilder config(String key, Object value) {
        this.config.put(key, value);
        return this;
    }
    
    /**
     * 批量添加配置
     * @param config 配置映射
     * @return 建造者实例
     */
    public FlowDefinitionBuilder config(Map<String, Object> config) {
        this.config.putAll(config);
        return this;
    }
    
    /**
     * 添加元数据
     * @param key 元数据键
     * @param value 元数据值
     * @return 建造者实例
     */
    public FlowDefinitionBuilder metadata(String key, Object value) {
        this.metadata.put(key, value);
        return this;
    }
    
    /**
     * 构建流程定义
     * @return 流程定义实例
     */
    public FlowDefinition build() {
        // 验证必要字段
        if (id == null || id.trim().isEmpty()) {
            throw new IllegalArgumentException("Flow ID cannot be null or empty");
        }
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("Flow name cannot be null or empty");
        }
        
        return new DefaultFlowDefinition(
            id, name, description, version,
            new ArrayList<>(steps),
            new HashMap<>(config),
            new HashMap<>(metadata)
        );
    }
}

🔧 StepDefinitionBuilder

java 复制代码
/**
 * 步骤定义建造者
 * 提供链式API来构建步骤定义
 */
public class StepDefinitionBuilder {
    
    private String id;
    private String name;
    private StepType type;
    private Map<String, Object> config = new HashMap<>();
    private String precondition;
    private List<String> dependencies = new ArrayList<>();
    private boolean parallel = false;
    
    /**
     * 创建建造者实例
     * @param id 步骤ID
     * @param type 步骤类型
     * @return 建造者实例
     */
    public static StepDefinitionBuilder builder(String id, StepType type) {
        return new StepDefinitionBuilder().id(id).type(type);
    }
    
    /**
     * 创建服务步骤
     * @param id 步骤ID
     * @param beanName Bean名称
     * @param methodName 方法名称
     * @return 建造者实例
     */
    public static StepDefinitionBuilder serviceStep(String id, String beanName, String methodName) {
        return builder(id, StepType.SERVICE)
            .config("beanName", beanName)
            .config("methodName", methodName);
    }
    
    /**
     * 创建条件步骤
     * @param id 步骤ID
     * @param condition 条件表达式
     * @return 建造者实例
     */
    public static StepDefinitionBuilder conditionalStep(String id, String condition) {
        return builder(id, StepType.CONDITIONAL)
            .config("condition", condition);
    }
    
    // ... 其他便捷方法
    
    /**
     * 构建步骤定义
     * @return 步骤定义实例
     */
    public StepDefinition build() {
        // 验证必要字段
        if (id == null || id.trim().isEmpty()) {
            throw new IllegalArgumentException("Step ID cannot be null or empty");
        }
        if (type == null) {
            throw new IllegalArgumentException("Step type cannot be null");
        }
        
        return new DefaultStepDefinition(
            id, name != null ? name : id, type,
            new HashMap<>(config),
            precondition,
            new ArrayList<>(dependencies),
            parallel
        );
    }
}

📊 执行状态模型

🎯 FlowExecutionResult - 流程执行结果

java 复制代码
/**
 * 流程执行结果
 * 包含流程执行的状态、结果数据和执行统计信息
 */
public class FlowExecutionResult {
    
    /**
     * 执行状态枚举
     */
    public enum Status {
        SUCCESS("成功"),
        FAILED("失败"),
        CANCELLED("已取消"),
        TIMEOUT("超时");
        
        private final String description;
        
        Status(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    private final String flowId;
    private final Status status;
    private final FlowContext context;
    private final List<StepExecutionResult> stepResults;
    private final long startTime;
    private final long endTime;
    private final Throwable exception;
    
    // 构造方法、getter方法等...
}

🔧 StepExecutionResult - 步骤执行结果

java 复制代码
/**
 * 步骤执行结果
 * 包含单个步骤的执行状态和结果信息
 */
public class StepExecutionResult {
    
    private final String stepId;
    private final StepType stepType;
    private final FlowExecutionResult.Status status;
    private final Object result;
    private final long startTime;
    private final long endTime;
    private final Throwable exception;
    
    // 构造方法、getter方法等...
}

🎨 UML类图

classDiagram class FlowDefinition { <> +getId() : String +getName() : String +getDescription() : String +getVersion() : String +getSteps() : List +getConfig() : Map +getMetadata() : Map } class StepDefinition { <> +getId() : String +getName() : String +getType() : StepType +getConfig() : Map +getPrecondition() : String +getDependencies() : List +isParallel() : boolean } class StepType { <> SIMPLE SERVICE CONDITIONAL SCRIPT_CONDITIONAL PARALLEL LOOP SCRIPT } class FlowContext { <> +get(key: String) : Object +put(key: String, value: Object) +getAll() : Map +createChild() : FlowContext +getParent() : FlowContext } class FlowDefinitionBuilder { +builder(id: String) : FlowDefinitionBuilder +name(name: String) : FlowDefinitionBuilder +addStep(step: StepDefinition) : FlowDefinitionBuilder +build() : FlowDefinition } class StepDefinitionBuilder { +builder(id: String, type: StepType) : StepDefinitionBuilder +serviceStep(name: String, service: String, method: String) : StepDefinitionBuilder +conditionalStep(name: String, condition: String) : StepDefinitionBuilder +build() : StepDefinition } FlowDefinition "1" *-- "*" StepDefinition : contains StepDefinition --> StepType : uses FlowDefinitionBuilder ..> FlowDefinition : creates StepDefinitionBuilder ..> StepDefinition : creates

🧪 使用示例

📝 编程式API示例

java 复制代码
// 创建流程定义
FlowDefinition userRegistrationFlow = FlowDefinitionBuilder
    .builder("user-registration")
    .name("用户注册流程")
    .description("处理用户注册的完整流程")
    .version("1.0.0")
    .addStep(
        StepDefinitionBuilder
            .serviceStep("validate-user", "userService", "validateUser")
            .name("用户验证")
            .build()
    )
    .addStep(
        StepDefinitionBuilder
            .conditionalStep("age-check", "context.get('age') >= 18")
            .name("年龄检查")
            .build()
    )
    .addStep(
        StepDefinitionBuilder
            .serviceStep("save-user", "userService", "saveUser")
            .name("保存用户")
            .build()
    )
    .config("timeout", 30000)
    .metadata("author", "杨杨杨大侠")
    .metadata("created", System.currentTimeMillis())
    .build();

// 创建执行上下文
FlowContext context = new DefaultFlowContext();
context.put("username", "张三");
context.put("age", 25);
context.put("email", "zhangsan@example.com");

// 执行流程(下一章实现)
// FlowEngine engine = new DefaultFlowEngine();
// FlowExecutionResult result = engine.execute(userRegistrationFlow, context);

🎯 设计亮点

✨ 1. 接口优先设计

  • 🎯 清晰的契约: 接口定义了明确的行为契约
  • 🔧 易于测试: 可以轻松创建Mock对象
  • 🚀 多种实现: 支持不同的实现策略

✨ 2. 建造者模式

  • 📝 链式调用: 提供流畅的API体验
  • 🛡️ 参数验证: 在构建时进行参数校验
  • 🎨 可读性强: 代码意图清晰明确

✨ 3. 枚举类型安全

  • 🔒 类型安全: 编译时检查,避免运行时错误
  • 📋 有限选择: 明确支持的步骤类型
  • 🔄 易于扩展: 新增类型只需修改枚举

✨ 4. 上下文层级结构

  • 🌳 数据隔离: 子上下文不影响父上下文
  • 📊 数据继承: 子上下文可以访问父上下文数据
  • 🔄 灵活传递: 支持复杂的数据传递场景

🎉 小结

在这一章中,我们完成了:

  • 🧩 设计了核心模型: FlowDefinition、StepDefinition、FlowContext
  • 🏷️ 定义了类型枚举: StepType支持多种步骤类型
  • 🏗️ 实现了建造者模式: 提供流畅的API体验
  • 📊 设计了执行结果模型: 完整的执行状态跟踪
  • 🎨 绘制了UML类图: 清晰展示模型关系

🚀 下一步

在下一章《流程引擎实现》中,我们将:

  • ⚙️ 实现FlowEngine核心执行逻辑
  • 🔧 设计StepExecutor执行器接口
  • 🎯 实现基础的步骤执行器
  • 🧪 编写完整的执行流程测试

💡 思考题:

  1. 如何设计才能支持步骤的动态配置?
  2. 上下文的线程安全如何保证?
  3. 如果要支持步骤的条件跳过,模型需要如何调整?
相关推荐
小兔兔吃萝卜1 小时前
Spring 创建 Bean 的 8 种主要方式
java·后端·spring
Java中文社群2 小时前
26届双非上岸记!快手之战~
java·后端·面试
whitepure2 小时前
万字详解Java中的面向对象(一)——设计原则
java·后端
autumnTop2 小时前
为什么访问不了同事的服务器或者ping不通地址了?
前端·后端·程序员
用户6757049885022 小时前
SQL 判断是否“存在”?99% 的人还在写错!
后端
PetterHillWater2 小时前
12 MCP Servers的介绍
后端·aigc·mcp
小Q圈圈3 小时前
BeanUtils 你走好!MapStruct 才是对象转换的真香神器!
后端