行为类模式(三):解释器(Interpreter)

定义

给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

UML

优点

  1. 将每一个语法规则表示成一个类,方便事先语言。
  2. 因为语法由许多类表示,所以你可以轻易地改变或扩展此语言
  3. 通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如打印格式的梅花或者进行复制的程序验证。

缺点

  1. 解释器模式会引起类膨胀,每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。
  2. 解释器模式采用递归调用方法,每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断点的调试下去,直到最小的语法单元。
  3. 效率问题,解释器模式由于使用了大量的循环和递归,效率是个不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。

应用场景

  1. 重复发生的问题可以使用解释器模式。
  2. 一个简单语法需要解释的场景。
  3. 可以处理脚本语言和编程语言,比如正则表达式。

示例

使用解释器模式完成一个两则运算器,要求输入表达式和每个符号的值得到表达式的最终结果。

Java

  1 import java.io.BufferedReader;
  2 import java.io.IOException;
  3 import java.io.InputStreamReader;
  4 import java.util.HashMap;
  5 import java.util.Stack;
  6 
  7 public class Main
  8 {
  9     public static void main(String[] args) throws IOException
 10     {
 11         String expStr = getExpStr();
 12         //赋值
 13         HashMap<String, Integer> var = getValue(expStr);
 14         Calculator cal = new Calculator(expStr);
 15         System.out.println("运算结果为:" + expStr + "=" + cal.run(var));
 16     }
 17 
 18     /**
 19      * 获得表达式
 20      */
 21     public static String getExpStr() throws IOException
 22     {
 23         System.out.print("请输入表达式:");
 24         return (new BufferedReader(new InputStreamReader(System.in))).readLine();
 25     }
 26 
 27     /**
 28      * 获得值映射
 29      */
 30     public static HashMap<String, Integer> getValue(String exprStr) throws IOException
 31     {
 32         HashMap<String, Integer> map = new HashMap<>();
 33         //解析有几个参数要传递
 34         for (char ch : exprStr.toCharArray())
 35         {
 36             if (ch != '+' && ch != '-')
 37             {
 38                 //解决重复参数的问题
 39                 if (!map.containsKey(String.valueOf(ch)))
 40                 {
 41                     System.out.print("请输入" + ch + "的值:");
 42                     String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
 43                     map.put(String.valueOf(ch), Integer.valueOf(in));
 44                 }
 45             }
 46         }
 47         return map;
 48     }
 49 
 50     /**
 51      * 表达式基类
 52      */
 53     public static abstract class Expression
 54     {
 55         /**
 56          * 解析公式和数值
 57          * @param var key值是是公式中的参数,value值是具体的数字
 58          * @return 结果
 59          */
 60         public abstract int interpreter(HashMap<String, Integer> var);
 61     }
 62 
 63     /**
 64      * 取值表达式
 65      */
 66     public static class VarExpression extends Expression
 67     {
 68         private String key;
 69 
 70         public VarExpression(String _key)
 71         {
 72             key = _key;
 73         }
 74 
 75         @Override
 76         public int interpreter(HashMap<String, Integer> var)
 77         {
 78             return var.get(key);
 79         }
 80     }
 81 
 82     /**
 83      * 运算表达式,仅关心左右两个值
 84      */
 85     public static abstract class SymbolExpression extends Expression
 86     {
 87         protected Expression left;
 88         protected Expression right;
 89 
 90         public SymbolExpression(Expression _left, Expression _right)
 91         {
 92             this.left = _left;
 93             this.right = _right;
 94         }
 95     }
 96 
 97     /**
 98      * 加法表达式处理
 99      */
100     public static class AddExpression extends SymbolExpression
101     {
102         public AddExpression(Expression _left, Expression _right)
103         {
104             super(_left, _right);
105         }
106 
107         public int interpreter(HashMap<String, Integer> var)
108         {
109             return super.left.interpreter(var) + super.right.interpreter(var);
110         }
111     }
112 
113     /**
114      * 减法表达式处理
115      */
116     public static class SubExpression extends SymbolExpression
117     {
118         public SubExpression(Expression _left, Expression _right)
119         {
120             super(_left, _right);
121         }
122 
123         public int interpreter(HashMap<String, Integer> var)
124         {
125             return super.left.interpreter(var) - super.right.interpreter(var);
126         }
127     }
128 
129     /**
130      * 运算类
131      */
132     public static class Calculator
133     {
134         //定义的表达式
135         private Expression expression;
136 
137         //构造函数传参,并解析
138         public Calculator(String expStr)
139         {
140             //定义一个堆栈,安排运算的先后顺序
141             Stack<Expression> stack = new Stack<Expression>();
142             //表达式拆分为字符数组
143             char[] charArray = expStr.toCharArray();
144             //运算
145             Expression left = null;
146             Expression right = null;
147             for (int i = 0; i < charArray.length; i++)
148             {
149                 switch (charArray[i])
150                 {
151                     case '+': //加法
152                         //加法结果放到堆栈中
153                         left = stack.pop();
154                         right = new VarExpression(String.valueOf(charArray[++i]));
155                         stack.push(new AddExpression(left, right));
156                         break;
157                     case '-': //减法
158                         left = stack.pop();
159                         right = new VarExpression(String.valueOf(charArray[++i]));
160                         stack.push(new SubExpression(left, right));
161                         break;
162                     default: //公式中的变量
163                         stack.push(new VarExpression(String.valueOf(charArray[i])));
164                 }
165             }
166             //把运算结果抛出来
167             this.expression = stack.pop();
168         }
169 
170         //开始运算
171         public int run(HashMap<String, Integer> var)
172         {
173             return this.expression.interpreter(var);
174         }
175     }
176 }
View Code
原文地址:https://www.cnblogs.com/hammerc/p/4743800.html