首页 > 编程笔记 > Java笔记 阅读:3

解释器模式(Java实现,附带实例)

解释器模式属于经典的 GoF 设计模式,能够把用另一种语言所写的字符序列解读成本语言中应有的动作。

解释器模式出现得比较早,因为很久以前就有人需要把 SQL 形式的语句解释成其他编程语言中的动作。

解释器模式定义两种对象来表示字符序列(也就是用户以另一种语言所写的词句)之中的两种构件:
解释器模式会把某个字符序列解释成由这两种对象所形成的一种结构。这些对象所表示的操作分别与用户所使用的那种语言中的某些语法相对应。

解释器模式将用户以另一种语言所写的一个句子(也就是一个字符序列)构造成由这两种对象形成的语法树(syntactic tree),并据此来解读那个句子的意思,把它用当前这种编程语言表达出来(这样的语法树可以用组合模式来构造)。

解释器模式在JDK中的运用

在 java.base 模块的 java.util.regex 包里,有个名为 Pattern 的类。该类的工具方法能够编译正则表达式,并将编译结果表示为 Pattern 对象。用户可以把自己期望的匹配规则以正则表达式的形式写成一串字符(这种表达式的语法与 Java 语言的语法不同),并将这串字符编译成 Pattern 对象。有了这样的对象,用户就能判断某个受测的 Java 字符串是否与这条规则相匹配。

在 JDK 里还有一个地方也出现了解释器模式,这就是 java.base 模块的 java.text 包。这个包里有个叫作 Format 的抽象类,让用户能够用另一种语法指定日期、时间与数字等格式,并根据当前的区域(locale)信息,将相应的数据调整为那种格式。

解释器模式实例演示

我们来定义一种简单的数学公式语言,并利用解释器模式把用户以这种语言所写的公式放在 Java 环境里执行。

这样的公式包含数字与运算符,其中的数字表示各个传感器的读数,运算符则表示这些读数与最终结果之间的关系(例如,提高了还是降低了最终的结果)。我们的范例代码会解读这样的公式,并把最终结果计算出来。

【实例】解释器模式能够把字符串形式的数学公式里的各个部分转化成相应的 Expression 型对象。
public static void main(String[] args) {
    System.out.println("Pattern Interpreter, sensors value");
    var stack = new Stack<Expression>();
    var formula = "1 - 3 + 100 + 1";
    var parsedFormula = formula.split(" ");

    var index = 0;
    while (index < parsedFormula.length) {
        var text = parsedFormula[index++];
        if (isOperator(text)) {
            var leftExp = stack.pop();
            var rightText = parsedFormula[index++];
            var rightExp = new IntegerExpression(rightText);
            var operatorExp = getEvaluationExpression(text, left, right);
            stack.push(operatorExp);
        } else {
            var exp = new IntegerExpression(text);
            stack.push(exp);
        }
    }
    System.out.println("Formula result: " + stack.pop().interpret());
}
程序输出结果如下:

Pattern Interpreter, math formula evaluation
Formula result: 99

该模式的基本元件是这个用来表示数学公式里各个单元的 Expression 接口,以及该接口的 interpret 方法。

程序会按照从左至右的顺序解析 1-3+100+1 这一公式,并在解析过程中对已经解析出来的这部分内容求值,等解析完公式中的最后一个部件(也就是解析完公式最后的 1),栈里剩下的那个元素就是整个公式的最终结果。由于公式里的每一个单元都封装成了相应的 Expression 子类型,因此这个解释器模式能够方便地予以扩展(参见下图)。


图 1 用 UML 类图演示程序在解析数学公式并求值的过程中所使用的各种部件

总结

解释器模式是一个很强大的设计模式,它让用户可以用另一种形式的文本来书写命令,并把用户所写的命令解读成当前这种编程语言里的相应构件。

解释器模式让设计者能够把那种语言里的相应单元跟当前这种编程语言中的相关元件在语法上对应起来,并将这些元件表示成一套体系(例如,本例中的 Expression 体系)。这样的话,这套体系就很容易扩展,甚至能够在程序运行期间动态地变化。

相关文章