一、解释器模式介绍
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
文法和句子的概念同编译原理中的描述相同,“文法”指语言的语法规则,而“句子”是语言集中的元素。
解释器模式角色:
- 抽象表达式(
Abstract Expression
)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法interpret()
。- 终结符表达式(
Terminal Expression
)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。- 非终结符表达式(
Nonterminal Expression
)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。- 环境(
Context
)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。此处我们的诉求:
- 通过代码结构对解释器模式进行了解即可。
二、解释器模式使用
2.1 示例关系:
2.2 代码实现:
/* *
* 1. 抽象表达式类。
*/
interface AbstractExpression {
/* *
* 解释方法。
*/
void interpret(String info);
}
/* *
* 2. 终结符表达式类。
*/
class TerminalExpression implements AbstractExpression {
@Override
public void interpret(String info) {
// 对终结符表达式的处理。
}
}
/* *
* 3. 非终结符表达式类。
*/
class NonterminalExpression implements AbstractExpression {
private AbstractExpression exp1;
private AbstractExpression exp2;
@Override
public void interpret(String info) {
//非对终结符表达式的处理
}
}
/* *
* 4. 环境类。
*/
class Context {
private AbstractExpression exp;
public Context() {
//数据初始化
}
public void operation(String info) {
//调用相关表达式类的解释方法
}
}
三、解释器模式总结
优点:
- 扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
- 容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
缺点:
- 执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
- 会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
- 可应用的场景比较少。在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到。
应用场景:
- 编译器、运算表达式计算、正则表达式等。
Spring SpelExpressionParser
源码使用到了该模式。注意:
- 解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。如果碰到对表达式的解释,在 Java 中可以用
Expression4J
或Jep
(Java expression parser
)等来设计。
四、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。