zoukankan      html  css  js  c++  java
  • 行为类模式(三):解释器(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
  • 相关阅读:
    关于JSON可能出现的错误,待更/todo
    mongoose的安装与使用(书签记录) 2017
    HTTP的学习记录3--HTTPS和HTTP
    HTTP的学习记录(二)头部
    HTTP(一)概述
    LeetCode 455. Assign Cookies
    LeetCode 453. Minimum Moves to Equal Array Elements
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 447. Number of Boomerangs
    LeetCode 416. Partition Equal Subset Sum
  • 原文地址:https://www.cnblogs.com/hammerc/p/4743800.html
Copyright © 2011-2022 走看看