设计模式—解释器模式

解释器模式

解释器模式(Interpreter Pattern)是一种按照规定语法进行解析的方案,在现在项目中使 用较少,其定义如下:Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language。

优点

解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改 相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。

缺点

  • 解释器模式会引起类膨胀。
  • 解释器模式采用递归调用方法。
  • 效率问题:解释器模式由于使用了大量的循环和递归,效率是一个不容忽视的问题,特别是一用于 解析复杂、冗长的语法时,效率是难以忍受的。

使用场景

  • 重复发生的问题可以使用解释器模式
  • 一个简单语法需要解释的场景

例子:模拟计算表达式

  • 抽象表达式
/**
 * 抽象表达式
 *
 * @author admin
 */
public abstract class Expression {
    /**
     * 解析公式和数值,其中var中的key值是公式中的参数,value值是具体的数字
     *
     * @param var 参数
     * @return 返回值
     */
    public abstract int interpreter(HashMap<String, Integer> var);
}
  • 变量解析器
import java.util.HashMap;

/**
 * 变量解析器
 *
 * @author admin
 */
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(key);
    }
}
  • 抽象运算符号解析器
/**
 * 抽象运算符号解析器
 *
 * @author admin
 */
public abstract class SymbolExpression extends Expression {
    protected Expression left;
    protected Expression right;

    /**
     * 所有的解析公式都应只关心自己左右两个表达式的结果
     *
     * @param left  左侧表达式
     * @param right 右侧表达式
     */
    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
}
  • 加法解析器
import java.util.HashMap;

/**
 * 加法解析器
 *
 * @author admin
 */
public class AddExpression extends SymbolExpression {
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}
  • 减法解析器
import java.util.HashMap;

/**
 * 减法解析器
 *
 * @author admin
 */
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);
    }
}
  • 解析器封装类
import java.util.HashMap;
import java.util.Stack;

/**
 * 解析器封装类
 *
 * @author admin
 */
public class Calculator {
    //定义表达式
    private Expression expression;

    //构造函数传参,并解析
    public Calculator(String expStr) {
        //定义一个栈,安排运算的先后顺序
        Stack<Expression> stack = new Stack<>();
        //表达式拆分为字符数组
        char[] charArray = expStr.toCharArray();
        //运算
        Expression left;
        Expression right;
        for (int i = 0; i < charArray.length; i++) {
            switch (charArray[i]) {
                case '+': //加法
                    //加法结果放到栈中
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    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: //公式中的变量
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
            }
        }
        //把运算结果抛出来
        this.expression = stack.pop();
    }

    //开始运算
    public int run(HashMap<String, Integer> var) {
        return this.expression.interpreter(var);
    }
}
  • 客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

public class Client {
    //运行四则运算
    public static void main(String[] args) throws IOException {
        String expStr = getExpStr();
        //赋值
        HashMap<String, Integer> var = getValue(expStr);
        Calculator cal = new Calculator(expStr);
        System.out.println("运算结果为:" + expStr + "=" + cal.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 exprStr) throws IOException {
        HashMap<String, Integer> map = new HashMap<>();
        //解析有几个参数要传递
        for (char ch : exprStr.toCharArray()) {
            if (ch != '+' && ch != '-') {
                //解决重复参数的问题
                if (!map.containsKey(String.valueOf(ch))) {
                    String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                    map.put(String.valueOf(ch), Integer.valueOf(in));
                }
            }
        }
        return map;
    }
}
posted @ 2023-07-25 12:46  弘一  阅读(16)  评论(0)    收藏  举报