定义

解释器模式(Interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

角色

  • AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。

  • TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。

  • NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。

  • Context: 环境类。包含解释器之外的一些全局信息。
  • Client: 客户类。

优缺点

优点:

  • 可扩展性比较好,灵活。

  • 增加了新的解释表达式的方式。

  • 易于实现文法。

缺点:

  • 执行效率比较低,可利用场景比较少。

  • 对于复杂的文法比较难维护。

实例(以乘除公式为例)

定义节点接口:

/**
 * 节点
 */
public interface Node {

    /**
     * 解释
     *
     * @return
     */
    int interpret();
}

节点具体实现类:

/**
 * 值节点
 */
public class ValueNode implements Node{

    private int value;

    public ValueNode(int value){
        this.value = value;
    }

    @Override
    public int interpret() {
        return this.value;
    }
}


/**
 * 符号节点抽象类
 */
public abstract class SymbolNode implements Node {

    protected Node left;
    protected Node right;

    public SymbolNode(Node left, Node right) {
        this.left = left;
        this.right = right;
    }
}

/**
 * 乘法
 */
public class MultiplyNode extends SymbolNode{

    public MultiplyNode(Node left, Node right) {
        super(left, right);
    }

    @Override
    public int interpret() {
        return left.interpret() * right.interpret();
    }
}

/**
 * 除法
 */
public class DivisionNode extends SymbolNode {
    public DivisionNode(Node left, Node right) {
        super(left, right);
    }

    @Override
    public int interpret() {
        return left.interpret() / right.interpret();
    }
}

计算器:

public class Calculator {

    private Node node;

    public void build(String statement) {
        Node left,right;
        Stack stack = new Stack();

        String[] statementArr = statement.split(" ");

        for (int i = 0; i < statementArr.length; i++) {
            if (statementArr[i].equalsIgnoreCase("*")) {
                left = (Node) stack.pop();
                int val = Integer.parseInt(statementArr[++i]);
                right = new ValueNode(val);
                stack.push(new MultiplyNode(left, right));
            } else if (statementArr[i].equalsIgnoreCase("/")) {
                left = (Node) stack.pop();
                int val = Integer.parseInt(statementArr[++i]);
                right = new ValueNode(val);
                stack.push(new DivisionNode(left, right));
            } else {
                stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
            }
        }
        this.node = (Node) stack.pop();
    }

    public int compute() {
        return node.interpret();
    }
}

测试:

public static void main(String[] args) {
    String statement = "3 * 2 * 4 / 6";

    Calculator calculator = new Calculator();

    calculator.build(statement);

    int result = calculator.compute();

    System.out.println(statement + " = " + result);
}

控制台输出:

3 * 2 * 4 / 6 = 4
01-23 04:23