🎯 目标 : 设计流程编排框架的核心数据模型和接口。项目地址: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执行器接口
- 🎯 实现基础的步骤执行器
- 🧪 编写完整的执行流程测试
💡 思考题:
- 如何设计才能支持步骤的动态配置?
- 上下文的线程安全如何保证?
- 如果要支持步骤的条件跳过,模型需要如何调整?