设计模式-解释器模式

402 阅读4分钟

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

就比如编译器可以将源码编译解释为机器码,让CPU 能进行识别开运㣔。解释器模式的作 用其实与编译器一样,都是将一些固定的文法(即语法)进行解释,构建出一个解释句子的解 释器。简单理解,解释器是一个简单语法分析工具,它可以识别句子语义,分离终结符号和非 终结符号,提取出需要的信息,让我们能针对不同的信息做出相应的处理。其核心思想是识别 文法,构建解释。

UML类图

image.png

在解释器模式中,每一种终结符和非终结符都有一个具体类与之对应,正因为使用类来表示每一条文法规则,所以系统将具有较好的灵活性和可扩展性。对于所有的终结符和非终结符,我们首先需要抽象出一个公共父类,即抽象表达式类。

public abstract class AbstractExpression {
    public  abstract void interpret(Context ctx);
}

终止符表达式,就比如如果做计算机解释器,A=B+C其中B和C对应的就是终止符表达式,终止符的代码算是比较简单的如下:(如果是计算机这里基本上就是返回对应的值就行了)

public class TerminalExpression extends AbstractExpression{
    @Override
    public void interpret(Context ctx) {
   
    }
}

非终结符表达式类那上面的计算器的例子来说其中加减乘除这些符号就是非终结符表达式,需要在interpret方法中对对用的表达式进行处理计算,到时候支持几种算法对应的额就是几种类,比如只支持加法和减法,需要创建两个类分别是加法的类 interpret中实现的就是left和right的加法运算然后会存到context中压栈

public class NonterminalExpression extends AbstractExpression{
    private TerminalExpression left;
    private TerminalExpression right;

    public NonterminalExpression(TerminalExpression left, TerminalExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public void interpret(Context ctx) {
        //对left和right进行响应的处理然后交给Context处理
        //如果是计算机的话这里就是对应的是加减乘除操作
    }
}

最后context主要是存储全局信息在进行聚德的解释操作后获取解释后的语言

public class Context {
    private final Stack<AbstractExpression> stack = new Stack<AbstractExpression>();

    public void parse(String expression) {
        //往环境类中设值
        //主要是一系列的操作然后存到栈中
        //这里主要是遍历这个字符串然后计算压栈处理
    }
    public int calculate() {
        //获取存储在环境类中的值
        //最后解释完之后这个栈中肯定只有一个值就是计算成功后的值然后返回
        return 0;
    }
}

解释器模式的优缺点

优点:

  1. 扩展性强:在解释器模式中由于语法是由很多类表示的,当语法规则更改时,只需修改 相应的非终结符表达式即可;若扩展语法时,只需添加相应非终结符类即可;
  2. 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。

缺点:

  1. 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
  2. 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

适用场景

  1. 一个简单语法需要解释的场景。
  2. 一些重复出现的问题可以用一种简单的语言来进行表达;
  3. 一个语言的文法较为简单