解释器模式

发布时间 2023-12-18 11:34:15作者: 求简君

解释器模式就像是一种自定义语言,我们可以定义该语言的语法规则,然后从中解析出具体的命令或表达式,最终执行相应的操作。

类似我们使用的编程语言,区别是有的先编译再执行(C#,JAVA),有的是边解释边执行(Javascript、Python)。

解释器分两个角色,一是表达式,二是上下文,表达式又分为终止符表达式,非终止符表达式。

代码示例

 

// 抽象表达式
public abstract class Expression {

    /**
     * 解释公式和数值, key 就是公式(表达式) 参数[a,b,c], value就是就是具体值
     *
     * @param var var
     * @return int
     */
    public abstract int interpreter(HashMap<String, Integer> var);

}

// 解释器
public class VarExpression extends Expression {

    private String key;

    public VarExpression(String key) {
        this.key = key;
    }

    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return var.get(this.key);
    }

}


public class SymbolExpression extends Expression {

    protected Expression left;
    protected Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return 0;
    }

}
public class SubExpression extends SymbolExpression {

    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) - super.right.interpreter(var);
    }

}
public class AddExpression extends SymbolExpression {

    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(HashMap<String, Integer> var) {
        //super.left.interpreter(var) : 返回 left 表达式对应的值 a = 10
        //super.right.interpreter(var): 返回right 表达式对应值 b = 20
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}


public class Calculator {

    private Expression expression;

    public Calculator(String expStr) {
        // 安排运算先后顺序
        Stack<Expression> stack = new Stack<>();
        // 表达式拆分成字符数组
        char[] charArray = expStr.toCharArray();

        Expression left;
        Expression right;
        //遍历我们的字符数组, 即遍历  [a, +, b]
        //针对不同的情况,做处理
        for (int i = 0; i < charArray.length; i++) {
            switch (charArray[i]) {
                case '+':
                    // 从stack取出left => "a"
                    left = stack.pop();
                    // 取出右表达式 "b"
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    // 然后根据得到left 和 right 构建 AddExpresson加入stack
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    //如果是一个 Var 就创建要给 VarExpression 对象,并push到 stack
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
                    break;
            }
        }
        //当遍历完整个 charArray 数组后,stack 就得到最后Expression
        this.expression = stack.pop();
    }

    public int run(HashMap<String, Integer> var) {
        //最后将表达式a+b和 var = {a=10,b=20}
        //然后传递给expression的interpreter进行解释执行
        return this.expression.interpreter(var);
    }
}


public static void main(String[] args) throws IOException {
    String expStr = getExpStr();
    HashMap<String, Integer> var = getValue(expStr);
    Calculator calculator = new Calculator(expStr);
    System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
}

public static String getExpStr() throws IOException {
    System.out.print("请输入表达式:");
    return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}

public static HashMap<String, Integer> getValue(String expStr) throws IOException {
    HashMap<String, Integer> map = new HashMap<>();
    for (char ch : expStr.toCharArray()) {
        if (ch != '+' && ch != '-') {
            if (!map.containsKey(String.valueOf(ch))) {
                System.out.print("请输入" + String.valueOf(ch) + "的值:");
                String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                map.put(String.valueOf(ch), Integer.valueOf(in));
            }
        }
    }
    return map;
}