解释器的访问者模式——基于实例类型调用方法



由于类型不兼容,下面的代码无法编译。然而,我正在尝试做一些类似的事情。据我所知,为了让这个工作,我必须采取超类,检查它是什么类型,并使用切换情况或一个讨厌的if else设置。我可以在这里利用多态性,并将访问方法放在ASTNode中,并在每个子类中重写它,但是,当我想确保这保留在解释器类中时,这是将逻辑放在ASTNode类中。

public class Test {
    private class ASTNode{
    }
    private class ExprNode extends ASTNode{
    }
    private class VarNode extends ASTNode{
    }
    private class Interpreter{
        public Interpreter(ASTNode node){
            this.visit(node);
        }
        public void visit(ExprNode node){
        }
        public void visit(VarNode node){
        }
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ASTNode node = new ExprNode();
        Interpreter interpreter =  new Interpreter(node);
    }
}

我正在构建一个解释器,我正在使用解释器的访问者模式。每种类型的节点都有一种访问方法。在我用python编写的示例中,它们使用getattr方法,该方法根据子类将调用分派到正确的方法。我不知道Java中有任何类似的东西。

最后,如果我在这里使用多态性,我将在ASTNode类中为解释器和赛门铁克分析器定义不同的访问方法。我喜欢在解释器类中有解释器逻辑的想法,但我讨厌基于子类类型有一个巨大的切换案例。

有什么想法吗?也许我错过了一个简单的技巧。

访问器模式的要点是通过处理单个子类上的访问器调用,用多态性代替"大开关"。这并不意味着逻辑包含在子类中,而是在访问者类上定义的。下面是在您的示例中的样子:

interface NodeVisitor {
    void visit(ExprNode node);
    void visit(VarNode node);
}
class Interpreter implements NodeVisitor {
    @Override
    public void visit(ExprNode node) {
        // custom logic here
    }
    @Override
    public void visit(VarNode node) {
        // custom logic here
    }
}
private class ASTNode {
    public abstract void accept(NodeVisitor visitor);
}
private class ExprNode extends ASTNode {
    @Override
    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }
}
private class VarNode extends ASTNode {
    @Override
    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }
}
public static void main(String[] args) {
    ASTNode node = new ExprNode();
    node.accept(new Interpreter());
}

最新更新