我有一个里面有图表的类(class)。我迭代该图并创建一个构建该图的字符串,然后将该字符串写入 Java 文件。 有没有更好的方法来做到这一点,我阅读了有关 JDT 和 CodeModel 的信息,但我确实需要一些关于如何使用它的提示。
编辑
我正在做一个正则表达式代码生成器,到目前为止,我已经将正则表达式转换为以有向图表示的 DFA(使用 grail 库)。当我拥有 DFA 时,下一步是生成一个具有三种方法的类,第一种方法构建相同的图 (DFA),第二种方法从一个节点移动到另一个节点,如果输入字符串被接受,第三种方法匹配。只有第一个方法根据正则表达式输入而改变,其他两个是静态的,并且对于每个生成的 java 类都是相同的。
我的基于字符串的方法是这样的:
import grail.interfaces.DirectedEdgeInterface;
import grail.interfaces.DirectedGraphInterface;
import grail.interfaces.DirectedNodeInterface;
import grail.interfaces.EdgeInterface;
import grail.iterators.EdgeIterator;
import grail.iterators.NodeIterator;
import grail.properties.GraphProperties;
import grail.setbased.SetBasedDirectedGraph;
public class ClassName {
private SetBasedDirectedGraph graph = new SetBasedDirectedGraph();
private static DirectedNodeInterface state;
private static DirectedNodeInterface currentState;
protected DirectedEdgeInterface edge;
public ClassName() {
buildGraph();
}
protected void buildGraph() {
// Creating Graph Nodes (Automaton States)
state = graph.createNode(3);
state.setProperty(GraphProperties.LABEL, "3");
state.setProperty(GraphProperties.DESCRIPTION, "null");
graph.addNode(state);
state = graph.createNode(2);
state.setProperty(GraphProperties.LABEL, "2");
state.setProperty(GraphProperties.DESCRIPTION, "null");
graph.addNode(state);
state = graph.createNode(1);
state.setProperty(GraphProperties.LABEL, "1");
state.setProperty(GraphProperties.DESCRIPTION, "Accepted");
graph.addNode(state);
state = graph.createNode(0);
state.setProperty(GraphProperties.LABEL, "0");
state.setProperty(GraphProperties.DESCRIPTION, "Initial");
graph.addNode(state);
.....
// Creating Graph Edges (Automaton Transitions)
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(2),
(DirectedNodeInterface) graph.getNode(1));
edge.setProperty((GraphProperties.LABEL), "0");
graph.addEdge(edge);
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(2),
(DirectedNodeInterface) graph.getNode(2));
edge.setProperty((GraphProperties.LABEL), "1");
graph.addEdge(edge);
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(1),
(DirectedNodeInterface) graph.getNode(1));
edge.setProperty((GraphProperties.LABEL), "0");
graph.addEdge(edge);
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(1),
(DirectedNodeInterface) graph.getNode(3));
edge.setProperty((GraphProperties.LABEL), "1");
graph.addEdge(edge);
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(0),
(DirectedNodeInterface) graph.getNode(1));
edge.setProperty((GraphProperties.LABEL), "0");
graph.addEdge(edge);
edge = graph.createEdge(null, (DirectedNodeInterface) graph.getNode(0),
(DirectedNodeInterface) graph.getNode(2));
edge.setProperty((GraphProperties.LABEL), "1");
graph.addEdge(edge);
}
}
最佳答案
另一种解决方案是坚持当前的技术,但提供一个带有 builder pattern 的小层。 .要实现该构建器,您只需付出少量的一次性努力,但会获得可读性更好的代码。
我实现了您代码的第一部分。使用适当的构建器,您可以编写:
graph = new GraphBuilder()
.createNode(3).setLabel("3").setDescription("null").add()
.createNode(2).setLabel("2").setDescription("null").add()
.createNode(1).setLabel("1").setDescription("Accepted").add()
.createNode(0).setLabel("0").setDescription("Initial").add()
// unimplemented start
.createEdge(2, 1).setLabel("0").add()
.createEdge(2, 2).setLabel("1").add()
.createEdge(1, 1).setLabel("0").add()
.createEdge(1, 3).setLabel("1").add()
.createEdge(0, 1).setLabel("0").add()
.createEdge(0, 2).setLabel("1").add()
// unimplemented end
.build();
更具可读性,不是吗?为此,您需要两个 builder 。首先是 GraphBuilder:
package at.corba.test.builder;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Builder for generating graphs.
* @author ChrLipp
*/
public class GraphBuilder {
/** List of StateBuilder, accesable via nodeNumber. */
Map<Integer, StateBuilder> stateBuilderMap = new LinkedHashMap<Integer, StateBuilder>();
/**
* Delegates node-specific building to NodeBuilder.
* @param nodeNumber Number of node to create
* @return NodeBuilder for the node instance to create.
*/
public StateBuilder createNode(final int nodeNumber) {
StateBuilder builder = new StateBuilder(this);
stateBuilderMap.put(nodeNumber, builder);
return builder;
}
/**
* Builder function to initialise the graph.
*/
public SetBasedDirectedGraph build() {
SetBasedDirectedGraph graph = new SetBasedDirectedGraph();
for (int key : stateBuilderMap.keySet()) {
StateBuilder builder = stateBuilderMap.get(key);
State state = graph.createNode(key);
state = builder.build(state);
graph.addNode(state);
}
return graph;
}
}
并且比 StateBuilder:
package at.corba.test.builder;
import java.util.HashMap;
import java.util.Map;
/**
* Builder for generating states.
* @author ChrLipp
*/
public class StateBuilder {
/** Parent builder */
private final GraphBuilder graphBuilder;
/** Properties for this node */
Map<GraphProperties, String> propertyMap = new HashMap<GraphProperties, String>();
/**
* ctor.
* @param graphBuilder Link to parent builder
* @param nodeNumber Node to create
*/
public StateBuilder(final GraphBuilder graphBuilder) {
this.graphBuilder = graphBuilder;
}
/**
* Property setter for property Label.
* @param label value for property label
* @return current NodeBuilder instance for method chaining
*/
public StateBuilder setLabel(final String label) {
propertyMap.put(GraphProperties.LABEL, label);
return this;
}
/**
* Property setter for description Label.
* @param description value for description label
* @return current NodeBuilder instance for method chaining
*/
public StateBuilder setDescription(final String description) {
propertyMap.put(GraphProperties.DESCRIPTION, description);
return this;
}
/**
* DSL function to close the node section and to return control to the parent builder.
* @return
*/
public GraphBuilder add() {
return graphBuilder;
}
/**
* Builder function to initialise the node.
* @return newly generated node
*/
public State build(final State state) {
for (GraphProperties key : propertyMap.keySet()) {
String value = propertyMap.get(key);
state.setProperty(key, value);
}
return state;
}
}
你会对边缘做同样的事情,但我没有实现这个:-)。 在 Groovy 中创建构建器更加容易(我的实现是用 Java 编写的构建器),例如参见 Make a builder .
关于java - Java 代码生成器的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10282177/