• 行为类模式(三):解释器(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
  • 相关阅读:
    Asp.net Mvc 中的模型绑定
    ActionResult 之HttpGet HttpPost
    Asp.net MVC 之 ActionResult
    Amazon MWS 上传数据 (三) 提交请求
    Amazon MWS 上传数据 (二) 构造请求
    Amazon MWS 上传数据 (一) 设置服务
    linq常用
    Nacos入门
    Post 方法参数写在body中和写在url中有什么区别
    强密码(必须包含字母、数字、特殊字符,长度8到16位)
  • 原文地址:https://www.cnblogs.com/hammerc/p/4743800.html
Copyright © 2020-2023  润新知