模式定义
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
代码示例
下面这个示例(简单计算器实现),对输入的一段文本(表达式),这里主要支持数字、变量和加法和乘法
- 先根据定义的文本规则将其符号化,得到一个符号化列表,同时在最后面加上终止符号,然后返回符号化列表,
- 然后根据规则取出token,将其组合解释成表达式。具体规则如下:
- 开头必须是变量或者数字;
- 先处理乘法在处理加法
- 得到表达式后,对表达式进行解析处理,然后得到结果。
具体代码如下:
定义支持的类型(变量、数字、加、乘、空格、终止符)
1 | /** |
1 | /** |
1 | /** |
1 | /** |
一下部分开始定义表达式
先是接口
1 | /** |
然后是四种类型的解释器
1 | /** |
1 | /** |
1 | /** |
1 | /** |
由于可能会存在解释异常,所以定义了一个异常类
1 | public class InterpreterException extends Exception { |
编写客户端运行
1 | public class Main { |
输出结果
1 | Attempting to evaluate: age * 10 + height * 1.5 |
从代码量来看,这个示例还是比较复杂的,由此可见编译器实现的复杂程度。
模式总结
对于一些固定文法构建一个解释句子的解释器。如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。注意由于解释器模式实现方式通常会或多或少的存在使用迭代(或递归)的场景,所以一定要做好终止条件的判断。
优缺点
优点
- 可扩展性比较好,灵活。
- 增加了新的解释表达式的方式。
- 易于实现简单文法。
缺点
- 可利用场景比较少;
- 对于复杂的文法比较难维护;
- 解释器模式会引起类膨胀;
- 解释器模式采用递归调用方法;
使用场景
通常使用在编译器、运算表达式计算中,另外Xml解析、Json解析都或多或少体现了解释器模式的应用。
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
- 一些重复出现的问题可以用一种简单的语言来进行表达。
- 一个简单语法需要解释的场景。
注意事项
- 需要注意构建语法树,定义终结符与非终结符的方式。
- 可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。
- 构建环境类来描述解释器运行的所需的环境,包含解释器之外的一些全局信息,一般是 HashMap。