标签:
定义:解释器模式是一种按照规定语法进行解析的方案,给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。实际上可以理解为是一个编译器(esclipse或者vc)或者是正则表达式。
类图:
以加减运算为例
业务需求:输入一个模型公式(加减四则运算),然后输入模型中的参数,运算出结果。
设计要求:
抽象表达式类
public abstract class Expression { //解析公式和数值,其中var中的key值是是公式中的参数,value值是具体的数字 public abstract int interpreter(HashMap<String,Integer> var); }
变量解析器
public class VarExpression extends Expression { private String key; public VarExpression(String _key){ this.key = _key; } //从map中取之 public int interpreter(HashMap<String, Integer> var) { return var.get(this.key); } }
加法解析器
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); } }
减法解析器
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); } }
运算器
public class Calculator { //定义的表达式 private Expression expression; //构造函数传参,并解析 public Calculator(String expStr){ //定义一个堆栈,安排运算的先后顺序 Stack<Expression> stack = new Stack<Expression>(); //表达式拆分为字符数组 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]))); } } //把运算结果抛出来 this.expression = stack.pop(); } //开始运算 public int run(HashMap<String,Integer> var){ return this.expression.interpreter(var); } }
客户端
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<String,Integer>(); //解析有几个参数要传递 for(char ch:exprStr.toCharArray()){ if(ch != ‘+‘ && ch != ‘-‘){ //解决重复参数的问题 if(!map.containsKey(String.valueOf(ch))){ System.out.print("请输入"+ch+"的值:"); String in = (new BufferedReader(new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch),Integer.valueOf(in)); } } } return map; } }
首先,要求输入公式。
请输入表达式:a+b-c
其次,要求输入公式中的参数。
请输入a的值:100
请输入b的值:20
请输入c的值:40
最后,运行出结果。
运算结果为:a+b-c=80
优点:
解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。
缺点
每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。
每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断点的调试下去,直到最小的语法单元。
解释器模式由于使用了大量的循环和递归,效率是个不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。
标签:
原文地址:http://www.cnblogs.com/sker/p/5551136.html