java - Java 代码生成器的更好方法?

标签 java code-generation eclipse-jdt sun-codemodel

我有一个里面有图表的类(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/

相关文章:

java - 在方向改变时查看相同的缩略图

java - 无法 Autowiring 。找不到 `Repository' 类型的 bean

java - 从字符串生成唯一的整数 ID

scala - Spark "CodeGenerator: failed to compile"与 Dataset.groupByKey

java - 潜在的空指针访问

java - 运行 Eclipse 插件

java - 我在修复继承中的 "getters"和 "setters"时遇到问题

java - 为什么 ComboBox 会消耗 KeyCode.ESCAPE 以及解决方法是什么?

python - Grako "code"代

eclipse - 如何找到 ITextViewer 内容的项目?