22解释器模式

2021/7/11 23:17:34

本文主要是介绍22解释器模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、解释器模式定义

1.解释器模式是指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。是一种按照规定的语法(文法)进行解析的模式,属于行为型模式。

2.其核心思想是识别文法,构建解释。分离终结符号和非终结符号,提取出需要的信息

3.解释器模式的应用场景:

  A.一些重复出现的问题可以用一种简单的语言来进行表达

  B.一个简单语法需要解释的场景

二、解释器模式示例

1.解释器模式一般包含4种角色:

  A.抽象表达式(Expression):负责定义一个解释方法interpret,交由具体子类进行具体解释

  B.终结符表达式(TerminalExpression):实现文法中与终结符有关的解释操作。文法中的每一个终结符都有一个具体终结表达式与之相对应,比如公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符(R1,R2)

  C.非终结符表达式(NonterminalExpression):实现文法中与非终结符有关的解释操作。文法中的每条规则都对应于一个非终结符表达式。非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,"+"就是非终结符,解析"+"的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式

  D.上下文环境类(Context):包含解释器之外的全局信息。它的任务一般是用来存放文法中各个终结符所对应的具体的值,比如R=R1+R2,给R1赋值100,给R2赋值200,这些信息需要存放到环境中

2.代码示例

  1 public interface IArithmeticInterpreter {
  2     int interpret();
  3 }
  4 
  5 public abstract class Interpreter implements IArithmeticInterpreter {
  6 
  7     protected IArithmeticInterpreter left;
  8     protected IArithmeticInterpreter right;
  9 
 10     public Interpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
 11         this.left = left;
 12         this.right = right;
 13     }
 14 }
 15 
 16 public class AddInterpreter extends Interpreter {
 17 
 18     public AddInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
 19         super(left, right);
 20     }
 21 
 22     public int interpret() {
 23         return this.left.interpret() + this.right.interpret();
 24     }
 25 }
 26 
 27 public class SubInterpreter extends Interpreter {
 28     public SubInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
 29         super(left, right);
 30     }
 31 
 32     public int interpret() {
 33         return this.left.interpret() - this.right.interpret();
 34     }
 35 }
 36 
 37 public class MultiInterpreter extends Interpreter {
 38 
 39     public MultiInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
 40         super(left,right);
 41     }
 42 
 43     public int interpret() {
 44         return this.left.interpret() * this.right.interpret();
 45     }
 46 
 47 }
 48 
 49 public class DivInterpreter extends Interpreter {
 50 
 51     public DivInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
 52         super(left,right);
 53     }
 54 
 55     public int interpret() {
 56         return this.left.interpret() / this.right.interpret();
 57     }
 58 
 59 }
 60 
 61 public class NumInterpreter implements IArithmeticInterpreter {
 62     private int value;
 63 
 64     public NumInterpreter(int value) {
 65         this.value = value;
 66     }
 67 
 68 
 69     public int interpret() {
 70         return this.value;
 71     }
 72 }
 73 
 74 public class GPCalculator {
 75     private Stack<IArithmeticInterpreter> stack = new Stack<IArithmeticInterpreter>();
 76 
 77     public GPCalculator(String expression) {
 78         this.parse(expression);
 79     }
 80 
 81     private void parse(String expression) {
 82         String [] elements = expression.split(" ");
 83         IArithmeticInterpreter leftExpr, rightExpr;
 84 
 85         for (int i = 0; i < elements.length ; i++) {
 86             String operator = elements[i];
 87             if (OperatorUtil.isOperator(operator)){
 88                 leftExpr = this.stack.pop();
 89                 rightExpr = new NumInterpreter(Integer.valueOf(elements[++i]));
 90                 System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
 91                 this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr,operator));
 92                 System.out.println("应用运算符: " + operator);
 93             }
 94             else{
 95                 NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements[i]));
 96                 this.stack.push(numInterpreter);
 97                 System.out.println("入栈: " + numInterpreter.interpret());
 98             }
 99         }
100     }
101 
102     public int calculate() {
103         return this.stack.pop().interpret();
104     }
105 }
106 
107 public class OperatorUtil {
108 
109     public static boolean isOperator(String symbol) {
110         return (symbol.equals("+") || symbol.equals("-") || symbol.equals("*"));
111     }
112 
113     public static Interpreter getInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right, String symbol) {
114         if (symbol.equals("+")) {
115             return new AddInterpreter(left, right);
116         } else if (symbol.equals("-")) {
117             return new SubInterpreter(left, right);
118         } else if (symbol.equals("*")) {
119             return new MultiInterpreter(left, right);
120         } else if (symbol.equals("/")) {
121             return new DivInterpreter(left, right);
122         }
123         return null;
124     }
125 }
126 
127 public class Test {
128 
129     public static void main(String[] args) {
130         System.out.println("result: " + new GPCalculator("10 + 30").calculate());
131         System.out.println("result: " + new GPCalculator("10 + 30 - 20").calculate());
132         System.out.println("result: " + new GPCalculator("100 * 2 + 400 * 1 + 66").calculate());
133     }
134 
135 }

3.解释器模式的优缺点

  A.优点

    a.扩展性强:在解释器模式中由于语法是由很多类表示的,当语法规则更改时,只需修改相应的非终结符表达式即可;若扩展语法时,只需添加相应非终结符类即可

    b.增加了新的解释表达式的方式

    c.易于实现文法:解释器模式对应的文法应当是比较简单且易于实现的,过于复杂的语法并不适合使用解释器模式

  B.缺点

    a.语法规则较复杂时,会引起类膨胀:解释器模式每个语法都要产生一个非终结符表达式,当语法规则比较复杂时,就会产生大量的解释类,增加系统维护难度

    b.执行效率比较低:解释器模式采用递归调用方法,每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,因此完整表达式的最终结果是通过从后往前递归调用的方式获取得到。当完整表达式层级较深时,解释效率下降,且出错时调试困难,因为递归迭代层级太深



这篇关于22解释器模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程