题记: 今天在工作中,实现业务流程图中流程图形化 Node & Flow的计算方式,其中大概是将大的流程图集合拆解成若干个小的子流程,这样在计算的时候,只需要计算子流程的结果就可以实现流程自动化;
其中,复杂流程拆分成多个基本单路径流程用到了有向无环图的设计方式
如图:
流程X
简单来说一下上述的实现过程
- 将复杂的流程图拆分成几个简单单路径的流程图
- 各个流程节点相互独立
- 在运行时,通过子节点的流程走向,将节点的输出数据当作下一个节点的输入数据
- 在非运行时:通过节点模型中存在已连接的其他节点,进行计算就可以
具体文章可以参考知乎:流程图形化 Node & Flow
具体实现:
package Graph4;
import java.util.*;
/**
* @author koala
* @ClassName GraphFlow
* @date 2019/6/11 20:06
* @Description
* @Version V1.0
*/
public class GraphFlow {
// 节点数
private int v;
/**
* 节点路径参照表
*/
private ArrayList<String>[] adjList;
/**
* 可参与计算的节点
*/
private Set<String> nodeSet = new HashSet<String>();
private Map<String,List<String>> adjMapList = new HashMap<String,List<String>>();
public GraphFlow(int vertices){
// 初始化当前节点数
this.v = vertices;
// 判断
initAdjList();
}
private void initAdjList()
{
// 初始化数组的长度
adjList = new ArrayList[v];
}
/**
* 所有参与计算的节点
* @param u
* @param v
*/
public void addEdge(String u, String v)
{
if(adjMapList.containsKey(u)){
adjMapList.get(u).add(v);
}else{
List<String> list = new ArrayList<>();
list.add(v);
adjMapList.put(u,list);
}
/**
* 遍历节点时,需要判断节点是否已经遍历,需要用一个集合去存放所有的节点
*/
nodeSet.add(u);
nodeSet.add(v);
}
// 遍历所有的路径
// 假设从路径S到路径D
public void printAllPaths(String s, String d)
{
// 是否已经遍历
Map<String,Boolean> isVisited = new HashMap<>();
for(String str: nodeSet){
isVisited.put(str,false);
}
ArrayList<String> pathList = new ArrayList<>();
// 第一个节点加入到数组里面
pathList.add(s);
//Call recursive utility
// 计算节点
printAllPathsUtil(s, d, isVisited, pathList);
}
private void printAllPathsUtil(String start, String end,
Map<String,Boolean> isVisited,
List<String> localPathList) {
// 标记当前节点
if(isVisited.containsKey(start)){
isVisited.put(start,false);
}
// 递归退出条件
if (start.equals(end))
{
// 输入当前节点路径
System.out.println(localPathList);
// 如果找到了,则需要将当前的节重新标记
isVisited.put(start,false);
return ;
}
// 遍历当前节点的集合
if(adjMapList.containsKey(start)){
for (String str : adjMapList.get(start)){
if(isVisited.containsKey(str)){
if(!isVisited.get(str)){
localPathList.add(str);
printAllPathsUtil(str,end,isVisited,localPathList);
// 在递归返回之后需要删除下一个递归的数据
localPathList.remove(str);
}
}
}
isVisited.put(start,false);
}else{
System.out.println(localPathList);
}
}
public static void main(String[] args)
{
// 构建图
GraphFlow g = new GraphFlow(8);
g.addEdge("A","B");
g.addEdge("A","C");
g.addEdge("B","D");
g.addEdge("C","E");
g.addEdge("C","F");
g.addEdge("E","G");
g.addEdge("F","G");
g.addEdge("G","H");
// arbitrary source
String start = "A";
// arbitrary destination
String end = "G";
System.out.println("Following are all different paths from "+start+" to "+end);
g.printAllPaths(start, end);
}
}
结果验证:
扩展:
上述的过程是计算2点之间所有的路径,其实还可以计算任意起点 到结束点的路径
`具体实现就是在 递归里面的退出节点,就需要重新调整递归函数的入参数,去掉end参数即可;
// 任意节点退出
if(!adjMapList.containsKey(start)){
// 输入当前节点路径
System.out.println(localPathList);
// 如果找到了,则需要将当前的节重新标记
isVisited.put(start,false);
return ;
}
总结:
- 业务流程化的工作流模型关键在于如何设置节点模式和 流程模型,节点模型和流程模式又是相互独立的
- 将流程集合拆分成若干个子流程更好的处理流程之间的计算关系,(后面还有子流程合并的时候如何计算,下一章节再讲)
`