使用Java制作流程图

使用Java制作流程图在 Java 语言以及其他程序设计语言中 程序包括顺序结构 SequentialSt 选择结构 SelectionStr 和循环结构 RepetitionSt 三种基本结构

使用Java制作流程图

1、设计思路

​ 在Java语言以及其他程序设计语言中,程序包括顺序结构(Sequential Structure)、选择结构(Selection Structure)和循环结构(Repetition Structure)三种基本结构。

这三种基本结构均可以使用程序流程图表示:
在这里插入图片描述

这三种基本结构的共同特点:

(1)每种结构只有一个出口

(2)在任何一种结构内,每个处理框都有机会被执行。

(3)对每个处理框来说,都应有一条从入口(a点)到出口(b点)的路径通过它。

(4)一个程序流程图都可以看作是若干个基本结构的组合或嵌套

2、设计实体类

边框节点实体类

@Data public class Node { 
    / * 节点ID */ private Long id; / * 输入框描述 */ private String name; / * 输入框类型 *START --起止框(开始框) *TASK -- 处理框 *DECISION --决策框 *IO --输入输出框 *END--起止框(结束框) * */ private String type; / *输入框X坐标 */ private String x; / *输入框Y坐标 */ private String y; public Set<Edge> nextNodes = new HashSet<>(); // 存放下游节点集合 

节点连接实体类

@Data public class Edge { 
    / * 起点 */ private Long source; / * 终点 */ private Long target; / * 条件 */ private String condition; / * 表达式 */ private String expression; } 

问题与解决方案:

测试用例:

{ 
   "nodes":[{ 
   "id":1,"name":"Start Node","type":"start","x":100,"y":100},{ 
   "id":2,"name":"Task 1","type":"task","x":200,"y":150},{ 
   "id":3,"name":"Decision","type":"decision","x":300,"y":200},{ 
   "id":4,"name":"Task 2","type":"task","x":200,"y":250},{ 
   "id":5,"name":"End Node","type":"end","x":100,"y":300}],"edges":[{ 
   "source":1,"target":2},{ 
   "source":2,"target":3},{ 
   "source":3,"target":4,"condition":"if X > 10","expression":" X > 10"},{ 
   "source":3,"target":5,"condition":"if X <= 10","expression":" X <= 10"}]} 
问题1

查询某个节点的所有下有节点

解决方案

应用DFS算法(深度优先搜索算法–Depth First Search,简称DFS:一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n))计算流程图下游节点;

1、分析数据

// 解析JSON数据,构建节点和边的关系图 public static Map<Long, Node> buildnodeListFromJson(String jsonStr) { 
    JSONObject flowChartJson = JSONObject.parseObject(jsonStr); JSONArray nodesJson = flowChartJson.getJSONArray("nodes"); JSONArray edgesJson = flowChartJson.getJSONArray("edges"); //统计边框信息 分组(方便查询获取) Map<Long, Node> nodeList = new HashMap<>(); for (int i = 0; i < nodesJson.size(); i++) { 
    JSONObject nodeJson = nodesJson.getJSONObject(i); Long nodeId = Long.valueOf(nodeJson.getString("id")); Node node = new Node(); node.setId(nodeId); node.setName(nodeJson.getString("name")); node.setType(nodeJson.getString("type")); node.setX(nodeJson.getString("x")); node.setY(nodeJson.getString("y")); nodeList.put(nodeId, node); } //统计边框下面节点 for (int i = 0; i < edgesJson.size(); i++) { 
    JSONObject edgeJson = edgesJson.getJSONObject(i); Long sourceNodeId = Long.valueOf(edgeJson.getString("source")); Long targetNodeId = Long.valueOf(edgeJson.getString("target")); Node sourceNode = nodeList.get(sourceNodeId); //下游节点信息 Edge edge = new Edge(); edge.setSource(sourceNodeId); edge.setTarget(targetNodeId); edge.setCondition(edgeJson.getString("condition")); edge.setExpression(edgeJson.getString("expression")) sourceNode.nextNodes.add(edge); } return nodeList; } 

查询节点下子节点:

//递归搜索指定节点的下游所有节点 public static List<Edge> dfs(Long startNodeId, Set<Long> visitedNodeIds, List<Edge> edges, Map<Long, Node> nodeList) { 
    Node node = nodeList.get(startNodeId); if (!(node == null || visitedNodeIds.contains(startNodeId))) { 
    visitedNodeIds.add(startNodeId); for (Edge edge : node.nextNodes) { 
    edges.add(edge); // 递归 dfs(edge.getTarget(), visitedNodeIds, edges, nodeList); } } return edges; } 

测试:

 public static void main(String[] args) { 
    String jsonStr = "{\"nodes\":[{\"id\":1,\"name\":\"Start Node\",\"type\":\"start\",\"x\":100,\"y\":100},{\"id\":2,\"name\":\"Task 1\",\"type\":\"task\",\"x\":200,\"y\":150},{\"id\":3,\"name\":\"Decision\",\"type\":\"decision\",\"x\":300,\"y\":200},{\"id\":4,\"name\":\"Task 2\",\"type\":\"task\",\"x\":200,\"y\":250},{\"id\":5,\"name\":\"End Node\",\"type\":\"end\",\"x\":100,\"y\":300}],\"edges\":[{\"source\":1,\"target\":2},{\"source\":2,\"target\":3},{\"source\":3,\"target\":4,\"condition\":\"if X > 10\"},{\"source\":3,\"target\":5,\"condition\":\"if X <= 10\"}]}"; // 处理Json Map<Long, Node> nodeList = buildnodeListFromJson(jsonStr); // 初始化边框节点信息 Long startNodeId = 1L; Set<Long> visitedNodeIds = new HashSet<>(); List<Edge> edges = new ArrayList<>(); // 进行下游节点搜索 dfs(startNodeId, visitedNodeIds, edges, nodeList); // 输出搜索结果 System.out.println("节点" + startNodeId + "的下游节点和边:"); for (Edge edge : edges) { 
    System.out.println(edge.getSource() + " (" + (StringUtils.isEmpty(edge.getCondition()) ? "" : edge.getCondition()) + ")========>" + edge.getTarget()); } } 

结果:

在这里插入图片描述

问题2:

通过判断条件处理下一步节点

解决方案:

因为判断条件为字符串,需要解析字符串进行逻辑判断,所以选择SpringEL (spring boot 需要1.3以上否则有注入风险)可以解析字符串逻辑,但是判断条件有限制,所以约定逻辑判断格式为 object(对象) + expression(条件) + value(数值)+other(其他条件-&、||、!)形式进行组装

/ * 通过判断条件查询下一节点 * * @param id * @param map * @param nodeList * @return */ public static List<Node> getNodes(Long id, Map<String, Object> map, Map<Long, Node> nodeList) { 
    Node startNode = nodeList.get(id); List<Node> endNode = new ArrayList<>(); if (startNode.nextNodes.size() >= 1) { 
    //遍历并筛选符合调件的下属边框 for (Edge edge : startNode.nextNodes) { 
    boolean result = getExpressionResult(map, "#a<#b*#c&&#d"); if (edge.getCondition() == null || result) { 
    endNode.add(nodeList.get(edge.getTarget())); } } } //终止框返回本身 if (startNode.nextNodes.size() < 1) { 
    endNode.add(startNode); } return endNode; } || result) { 
    endNode.add(nodeList.get(edge.getTarget())); } } } //终止框返回本身 if (startNode.nextNodes.size() < 1) { 
    endNode.add(startNode); } return endNode; } 
今天的文章 使用Java制作流程图分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2024-12-27 07:40
下一篇 2024-12-27 07:33

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/96417.html