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

时间:2016-11-15 02:50:25

标签: java

由于类型不兼容,下面的代码无法编译。但是,我正在尝试做类似的事情。为了让我知道这一点,我将不得不采取超类并检查它是什么类型,并使用开关案例或讨厌if if set。我可以在这里利用多态,并将访问方法放在ASTNode中并在每个sublcass中覆盖它,但是,当我想确保它保留在Interpreter类中时,它将逻辑放在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);
    }
}

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

最后,如果我在这里使用多态,我将在ASTNode类中为Interpreter和Symantic Analyzer定义不同的访问方法。我喜欢在解释器类中使用解释器逻辑的想法,但我不愿意基于子类类型拥有一个巨大的开关案例。

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

1 个答案:

答案 0 :(得分:2)

访问者模式的要点是通过处理单个子类上的访问者调用来用多态替换“巨大的开关”。这并不意味着 logic 包含在子类中,而是在访问者类中定义。以下是您的示例中的内容:

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());
}