我正在编写用于流程图执行的模块。流程图包含要执行的任务的数量。每个任务都有自己的功能。我使用图形存储流程执行。我使用有向非循环图来存储它
DirectedGraph.java
public class DirectedGraph<T> implements Iterable<T> , Serializable {
/**
*
*/
private final ConcurrentHashMap<T,Set<T>> graph = new ConcurrentHashMap<>();
public boolean addNode(T node){
if(graph.containsKey(node))
return false;
//Add node to the graph
graph.put(node, Collections.synchronizedSet(new HashSet<T>()));
return true;
}
public void addEdge(T start,T end){
if(!graph.containsKey(start) || !graph.containsKey(end))
throw new NoSuchElementException("One or both of the vertex are missing.");
/*Adding edge in the graph*/
graph.get(start).add(end);
}
/*
Other method for iterator,size etc.
*/
}
添加到图表后,我正在执行拓扑排序。执行排序后,我得到任务列表。
任务有以下结构。
class Task{
int id;
int activityId;
String activityType;
ArratList<Integer> inputIds;
ArratList<Integer> outputIds;
}
每个任务都有自己的ID。 inputIds包含它的依赖任务,outputIds包含需要执行的任务。活动类型可以是[Task,Decision]。
我认为这就像是一个工作流程执行。那么执行工作流程执行的最佳方法是什么。
答案 0 :(得分:0)
我建议的两个都是基于处理拓扑排序的节点列表。
多态任务/决策
给任务一个抽象方法void execute(ExecutionContext context)
。每个TaskType都有自己的实现,其中对执行上下文的所有更改都已完成。如果要返回信息,结果类型可能会有所不同(例如,如果流程应继续)。如果你只有一次传球并且不希望在同一个名单上多次传球,你应该更喜欢这个。
<强>访问者/口译强>
使用访问者设计模式,添加方法void apply(TaskVisitor visitor)
。 TaskVisitor每个activityType有一个visitXXX方法。如果您在任务列表上执行了不同的操作(例如,类型检查,验证,解释),则建议使用此方法。
在这两种情况下,最好使用不同的Task子类型来区分不同的活动类型(实际上使用字段activityType),因为您可以以多态方式区分不同的行为,而不是使用if / switch-cascades。
答案 1 :(得分:0)
我为这些用例构建了一个名为Dexecutor的框架,您可以查看source code,并探索使用的最佳实践和设计模式。您可以找到类似的datastructure。
这是workflow example,可以使用Dexecutor
实现