四则运算问题
通过解释器模式来实现四则运算,如计算a+b-c的值,具体要求 :
- 先输入表达式的形式,比如 a+b+c-d+e,要求表达式的字母不能重复。
- 再分别输入a,b,c,d,e的值。
- 最后输出运算结果。
解释器模式
基本介绍
- 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看作是解释器。
- 解释器模式:是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,是用该解释器来解释语言中的句子(表达式)。
解释器模式解决四则运算问题
为了实现方便,并简化问题。我们只引入加法和减法。
- UML类图
- 代码实现
Expression 类:
变量解释器 VarExpression 类:import java.util.HashMap; public abstract class Expression { public abstract int interpreter(HashMap<String, Integer> var); }
符号表达式 SymbolExpression 类:import java.util.HashMap; /** * 变量的解释器 */ 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); } }
加法符号 AddExpression 类:import java.util.HashMap; 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; } }
减法符号 SubExpression 类:import java.util.HashMap; public class AddExpression extends SymbolExpression { public AddExpression(Expression left, Expression right) { super(left, right); } public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) + super.right.interpreter(var); } }
Calculator 计算器类:import java.util.HashMap; public class SubExpression extends SymbolExpression { public SubExpression(Expression left, Expression right) { super(left, right); } public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) - super.right.interpreter(var); } }
Client 类:import java.util.HashMap; import java.util.Stack; public class Calculator { private Expression expression; public Calculator(String expStr) { Stack<Expression> stack = new Stack<>(); char[] charArray = expStr.toCharArray(); Expression left = null; Expression right = null; 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]))); break; } } 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 calculator = new Calculator(expStr); System.out.println("运算结果:" + expStr + "=" + calculator.run(var)); } private 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.println("请输入" + String.valueOf(ch) + "的直:"); String in = (new BufferedReader(new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch), Integer.valueOf(in)); } } } return map; } private static String getExpStr() throws IOException { System.out.println("请输入表达式:"); return (new BufferedReader(new InputStreamReader(System.in))).readLine(); } }
解释器模式在Spring框架中的应用
例如:
public class Main {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("10 * (2 + 1) * 1 + 66");
int result = (Integer) expression.getValue();
System.out.println(result);
}
}
- UML类图
- 总结
- Expression是一个表达式接口,下面有不同的实现类,如SpelExpression。
- 使用的时候,根据创建的不同的 ExpressionParser(如InternalSpelExpressionParser或SpelExpressionParser)对象,返回不同的表达式Expression对象。
- getValue()方法是一个解释器方法。不同的Expressioin调用getValue方法,解释表达式,得到结果。
解释器模式的注意事项和细节
- 当一个语言需要解释执行,可以将该语言中的句子表示为一个抽象的语法树,就可以考虑使用解释器模式,让程序具有良好的扩展性。
- 应用场景:编译器、运算表达式计算、正则表达式、机器人等。
- 使用解释器可能带来的问题:解释器模式会引起类膨胀、解释器模式采用递归调用方法,将可能导致调式空难,执行效率低。