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. 如果要支持步骤的条件跳过,模型需要如何调整?
相关推荐
Marktowin2 小时前
Mybatis-Plus更新操作时的一个坑
java·后端
赵文宇2 小时前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端
程序员爱钓鱼2 小时前
Node.js 编程实战:即时聊天应用 —— WebSocket 实现实时通信
前端·后端·node.js
Libby博仙3 小时前
Spring Boot 条件化注解深度解析
java·spring boot·后端
源代码•宸3 小时前
Golang原理剖析(Map 源码梳理)
经验分享·后端·算法·leetcode·golang·map
小周在成长3 小时前
动态SQL与MyBatis动态SQL最佳实践
后端
瓦尔登湖懒羊羊4 小时前
TCP的自我介绍
后端
小周在成长4 小时前
MyBatis 动态SQL学习
后端
子非鱼9214 小时前
SpringBoot快速上手
java·spring boot·后端
我爱娃哈哈4 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端