解释器模式的使用

2022-07-02  本文已影响0人  文景大大

一、模式介绍

解释器模式就是定义多种解释器,为文本或者符号进行解释行为的逻辑意义,比如1+2,需要两种解释器,一种数值解释器告诉我们1和2这种符号代表就是数值1和2,还有一种就是符号解释器,告诉我们+号代表的是前后两个数值做加法运算。因此我们可以看出,解释器模式就像是我们的代码编译器,将固定文法的内容进行解释,构建出计算机能识别的内容进行计算。

核心就是:识别文法(符号)、构建解释。一般包含如下三种角色:

我们以一个计算整数加减法的计算器为例:

/**
 * 抽象表达式,定义解释符号的行为
 */
public abstract class Expression {
    public abstract int interpreter(HashMap<String,Integer> var);
}
/**
 * 数值表达式,对自然数符号进行解释
 */
public class VarExpression extends Expression{
    private String name;

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

    /**
     * 自然数符号的解释就是返回当前name对应的数值
     * @param var
     * @return
     */
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return var.get(name);
    }
}
/**
 * 运算符表达式,对运算符进行解释
 */
public class SymbolExpression extends Expression{
    protected Expression left;
    protected Expression right;

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

    /**
     * 运算符分为加号运算符和减号运算符,具体解释逻辑需要在子类中实现
     * @param var
     * @return
     */
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return 0;
    }
}
/**
 * 加号运算符表达式,对加号运算符进行解释
 */
public class AddExpression extends SymbolExpression{
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    /**
     * 加号运算符的解释就是两数相加的结果
     * @param var
     * @return
     */
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}
/**
 * 减号运算符表达式,对减号运算符进行解释
 */
public class SubExpression extends SymbolExpression{
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    /**
     * 减号运算符的解释就是两数相减的结果
     * @param var
     * @return
     */
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) - super.right.interpreter(var);
    }
}
public class Calculator {
    private Expression expression;

    public Calculator(String expressionStrings){
        // 使用栈这种数据结构来处理加减运算
        Stack<Expression> stack = new Stack<>();
        char[] chars = expressionStrings.toCharArray();
        Expression left = null;
        Expression right = null;

        // 1+1-2这样的表达式在如下循环后,stack中只会有有一个元素
        for (int i=0;i<chars.length;i++){
            switch (chars[i]) {
                case '+':
                    // 取出第一个加数
                    left = stack.pop();
                    // 获取第二个加数
                    right = new VarExpression(String.valueOf(chars[++i]));
                    // 构造加号表达式后再入栈,等待和后面的表达式进行递归计算
                    stack.push(new AddExpression(left,right));
                    break;
                case '-':
                    // 取出被减数
                    left = stack.pop();
                    // 获取减数
                    right = new VarExpression(String.valueOf(chars[++i]));
                    // 构造减号表达式后再入栈,等待和后面的表达式进行递归计算
                    stack.push(new SubExpression(left,right));
                    break;
                default:
                    // 数值符号,name就指定为当前数值,再入栈,等待和后面的表达式进行递归计算
                    stack.push(new VarExpression(String.valueOf(chars[i])));
                    break;
            }
        }

        // 获取stack中最终形成的唯一的元素
        this.expression = stack.pop();
    }

    /**
     * 对当前表达式进行递归解释
     * @param var
     * @return
     */
    public int doCalculate(HashMap<String, Integer> var){
        return this.expression.interpreter(var);
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) {
        String expressionStrins = "a+b-c";
        HashMap<String,Integer> vars = new HashMap<>();
        vars.put("a",1);
        vars.put("b",1);
        vars.put("c",2);

        Calculator casio = new Calculator(expressionStrins);
        Integer result = casio.doCalculate(vars);
        log.info("计算结果为:{}", result);
    }
}

二、使用场景

三、模式总结

3.1 优点

3.2 缺点

上一篇 下一篇

猜你喜欢

热点阅读