java - 通过访问者评估树表达

标签 java oop design-patterns visitor-pattern

我有一个复合设计模式的表达式:

interface TreeExpression{
    void accept(Visitor visitor);
}

abstract class Operator{
    TreeExpression childA;
    TreeExpression childB;

    Operator(TreeExpression a, TreeExpression b){
        this.childA = a;
        this.childB = b;
    }
}

class PlusTreeExpression extends Operator implements TreeExpression{
    public PlusTreeExpression(TreeExpression a, TreeExpression b) {
        super(a, b);
    }

    public void accept(Visitor visitor) {
        this.childA.accept(visitor);
        visitor.visit(this);
        this.childB.accept(visitor);
    }
}

class MultiplyTreeExpression extends Operator implements TreeExpression{
    public MultiplyTreeExpression(TreeExpression a, TreeExpression b) {
        super(a, b);
    }

    public void accept(Visitor visitor) {
        this.childA.accept(visitor);
        visitor.visit(this);
        this.childB.accept(visitor);
    }
}

class IntegerNode implements TreeExpression{
    Integer value;

    IntegerNode(int v){
        this.value = v;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

和从表达式中获取字符串的访问者:

interface Visitor{
    void visit(PlusTreeExpression tree);
    void visit(MultiplyTreeExpression tree);
    void visit(IntegerNode node);
}

class PrintVisitor implements Visitor{
public StringBuffer result = new StringBuffer();


    public void visit(IntegerNode node) {
        result.append(node.value);
    }

    public void visit(PlusTreeExpression tree) {
        result.append("+");
    }

    public void visit(MultiplyTreeExpression tree) {
        result.append("*");
    }

这个 visitore 有效,现在我正在尝试让 visitor 评估表达式,但这里我遇到了问题。我尝试了几种方法,但我不知道如何在不更改现有代码的情况下将子树的值(value)获取到根中。

最佳答案

据我所知,这里的问题是您要定义如何在树本身而不是访问者中遍历树。虽然这是一种有效的方法(设计模式确实有变体),但我认为在这种情况下最好将树结构与遍历顺序(前序、中序、后序)分离。事实上,教授此模式的典型练习是编写三个访问者,每个访问者执行不同的遍历。

在你的情况下我会:

  1. 像您一样将表达式表示为树,但从接受遍历部分中移除。在您的代码中,接受看起来像:

    public void accept(Visitor visitor)
    {
        visitor.visit(this);
    }
    
  2. 为节点的子节点定义公共(public) getter,以便访问者可以访问它们(getChildA()getChildB()getValue ()).

  3. 为您需要的遍历类型编写访问者。为了评估表达式,您通常会使用后序,而为了打印可以按顺序使用的表达式(如您的示例所示)。因此,为了评估表达式,您将以如下所示的内容结尾:

    class EvalVisitor implements Visitor{
    
            public Integer visit(IntegerNode node) {
                return node.getValue();
            }
    
            public Integer visit(PlusTreeExpression tree) {
                return this.visit(tree.getChildA()) + this.visit(tree.getChildB());
            }
    
            public Integer visit(MultiplyTreeExpression tree) {
                return this.visit(tree.getChildA()) * this.visit(tree.getChildB());
            }
        }
    

HTH

关于java - 通过访问者评估树表达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14469775/

相关文章:

java - 如何在javafx中更改所有 subview 文本大小

java - 将 sql 中的多个列映射到 java 对象

PHP OOP - 类内的 MySQL 连接

c++ - 在 C++ 层次结构中放置 util 方法的位置

java - 如何从 JSP 获取图像 blob 到 JavaScript?

java - 异常 : java.net.BindException:无法分配请求的地址

swift - 在调用 super.init() 之前实例化调用自身的属性

java - Lombok @NonNull 与 Validate.notNull

javascript - 更新 JavaScript 对象创建模式

Java 提取标签和属性之间的文本