工作流引擎设计与实现·模型抽象

前言

上文对工作流进行了一些基本的介绍,有了基础篇的内容,相信我们可以很容易抽象了一些实体模型:流程模型、开始节点模型、结束节点模型、任务节点模型、决策节点模型、分支节点模型、合并节点模型、边模型。

基础模型

我们把模型进行进一步抽象,可以得到基础模型,基础模型只包含两个属性,唯一编码和显示名称。

public class BaseModel {
    private String name; // 唯一编码
    private String displayName; // 显示名称
}

模型行为

如果按照面向对象来看,流程模型本身除了属性外,还应该具有方法和行为,即节点和边所能做的事,这里用Action接口来定义。

public interface Action {
    public void execute(Execution execution);
}

因每个流程模型执行的条件可能不一样,这里统一使用Execution类来定义,下面先简单定义其必要属性,后续根据需要再追加。

public class Execution {
    private String processInstanceId; // 流程实例ID
    private String processTaskId; // 当前流程任务ID
    // 执行对象扩展参数
    private Dict args;
}

节点模型

流程模型由节点模型和边构成,节点的类型虽然很多,但是依然可以对其进行进一步抽象。节点都有自己通用性的行为,如前置拦截、后置拦截、日志处理等,除了通用性行为外,还可以根据子类不同的特性,实现exec抽象方法。

public abstract class NodeModel extends BaseModel implements Action {
    private String layout;// 布局属性(x,y,w,h)
    // 输入边集合
    private List<TransitionModel> inputs = new ArrayList<TransitionModel>();
    // 输出边集合
    private List<TransitionModel> outputs = new ArrayList<TransitionModel>();
    private String preInterceptors; // 节点前置拦截器
    private String postInterceptors; // 节点后置拦截器

    /**
     * 由子类自定义执行方法
     * @param execution
     */
    @Override
    abstract void exec(Execution execution);
    @Override
    public void execute(Execution execution) {
        // 1. 调用前置拦截器
        // 2. 调用子类的exec方法
        // 3. 调用后置拦截器
        exec(execution);
    }
}

有了节点模型后,其他具体的节点模型就会显示相对简单。

开始节点模型

开始节点主要继承节点模型并实现其exec方法。

public class StartModel extends NodeModel {
    @Override
    public void exec(Execution execution) {
        // 执行开始节点自定义执行逻辑
    }
}

结束节点模型

结束节点也是继承节点模型并实现exec方法。

public class EndModel extends NodeModel {
    @Override
    public void exec(Execution execution) {
        // 执行结束节点自定义执行逻辑
    }
}

任务节点模型

任务节点是流程中非常重要的节点,其拥有更多自己的属性。当然,下面只是把常用的属性罗列出来,后续也根据具体实现的业务,增加和删除其属性。

image.png

public class TaskModel extends NodeModel {
    private String form; // 表单标识
    private String assignee; // 参与人
    private String assignmentHandler; // 参与人处理类
    private TaskTypeEnum taskType; // 任务类型(主办/协办)
    private TaskPerformTypeEnum performType; // 参与类型(普通参与/会签参与)
    private String reminderTime; // 提醒时间
    private String reminderRepeat; // 重复提醒间隔
    private String expireTime; // 期待任务完成时间变量key
    private String autoExecute; // 到期是否自动执行Y/N
    private String callback; // 自动执行回调类
    private Dict ext = Dict.create(); // 自定义扩展属性
    @Override
    public void exec(Execution execution) {
        // 执行任务节点自定义执行逻辑
    }
}

决策节点模型

决策节点也是一种特殊节点,其会有决策表达式,和决策处理类属性,主要用于动态计算下一个节点的走向。

public class DecisionModel extends NodeModel {
    private String expr; // 决策表达式
    private String handleClass; // 决策处理类
    @Override
    public void exec(Execution execution) {
        // 执行决策节点自定义执行逻辑
    }
}

分支节点模型

当用到并行流程的时候,该节点就派上用场了,这里只是先简单定义,后续也会根据具体的业务需要,扩展新的属性。

public class ForkModel extends NodeModel {
    @Override
    public void exec(Execution execution) {
        // 执行分支节点自定义执行逻辑
    }
}

合并节点模型

合并节点和分支节点是一起出来的,这里也是先按照最基础的定义。

public class JoinModel extends NodeModel {
    @Override
    public void exec(Execution execution) {
        // 执行合并节点自定义执行逻辑
    }
}

边模型

两节点连线,就构成一条边,所以边的关系属性就是source和target,边也有自己的执行方法。

public class TransitionModel extends BaseModel implements Action {
    private NodeModel source; // 边源节点引用
    private NodeModel target; // 边目标节点引用
    private String to; // 目标节点名称
    private String expr; // 边表达式
    private String g; // 边点坐标集合(x1,y1;x2,y2,x3,y3……)开始、拐角、结束
    private boolean enabled; // 是否可执行
    @Override
    public void execute(Execution execution) {
        
    }
}

流程模型

有了上面的元素,那么流程模型就很容易得到如下定义:

image.png

public class ProcessModel extends BaseModel {
    private String type; // 流程定义分类
    private String instanceUrl; // 启动实例要填写的表单key
    private String expireTime; // 期待完成时间变量key
    private String instanceNoClass; // 实例编号生成器实现类
    // 流程定义的所有节点
    private List<NodeModel> nodes = new ArrayList<NodeModel>();
    // 流程定义的所有任务节点
    private List<TaskModel> tasks = new ArrayList<TaskModel>();

}

来个简单的模型对象

public class BuildProcessTest {
  @Test
  public void buildProcessModel() {
        ProcessModel processModel = new ProcessModel();
        StartModel startModel = new StartModel();
        startModel.setName("start");
        startModel.setDisplayName("开始");
        processModel.getNodes().add(startModel);
        TransitionModel t1 = new TransitionModel();
        t1.setName("t1");
        t1.setTo("apply");
        t1.setSource(startModel);
        startModel.getOutputs().add(t1);

        TaskModel applyTaskModel = new TaskModel();
        t1.setTarget(applyTaskModel);
        applyTaskModel.setName("apply");
        applyTaskModel.setDisplayName("请假申请");
        processModel.getNodes().add(applyTaskModel);
        processModel.getTasks().add(applyTaskModel);
        TransitionModel t2 = new TransitionModel();
        t2.setName("t2");
        t2.setTo("deptApprove");
        t2.setSource(applyTaskModel);
        applyTaskModel.getOutputs().add(t2);

        TaskModel deptApproveTaskModel = new TaskModel();
        t2.setTarget(deptApproveTaskModel);
        deptApproveTaskModel.setName("deptApprove");
        deptApproveTaskModel.setDisplayName("部门领导审批");
        processModel.getNodes().add(deptApproveTaskModel);
        processModel.getTasks().add(deptApproveTaskModel);

        TransitionModel t3 = new TransitionModel();
        t3.setName("t3");
        t3.setTo("end");
        t3.setSource(deptApproveTaskModel);
        deptApproveTaskModel.getOutputs().add(t3);

        EndModel endModel = new EndModel();
        t3.setTarget(endModel);
        endModel.setName("end");
        endModel.setDisplayName("结束");
        processModel.getNodes().add(endModel);
      
  }
}

加入组织

请在微信中打开:
《立东和他的朋友们》

fenchuan.jpg

相关源码

mldong-flow-demo-01

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值