一.定义
给定一门语言,定义它文法的一种表示,并定义一个解释器,该解释器使用所定义的文法规则来解释语言中的句子。(别名叫翻译器模式)
二.类图
- AbstractExpression抽象解释器。具体的解释任务由各个实现类完成,具体的解释器分别由TermianlExpression和NonterminalExpression完成。
- TerminalExpression终结符表达式。实现与文法中元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。如a+b+c中a、b、c
- NonterminalExpression非终结符表达式。文法中的每条规则对应于一个非终结表达式,如a+b-c中的+、-。
- Context环境角色。
三.优点
解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。
四.缺点
- 会引起类膨胀。
- 采用递归调用,调试比较困难。
- 由于使用了大量的循环和递归,效率是一个不容忽视的问题。
五.使用场景
- 重复发生的问题可以使用解释器模式。例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,但是非终结符表达式就需要指定了。
- 一个简单语法需要解释的场景。为什么是简单?因为非终结表达是越多,意味着文法规则越多,复杂度越高,而且类间还要进行递归调用。
- 解释器模式在实际的系统开发中使用的非常少,因为它会引起效率、性能以及维护等问题,一般在大中型的框架型项目能够找到它的身影,如数据分析工具、报表设计工具等。如必须使用时,可以考虑开源产品Expression4J、MESP(Math Expression String Paser)等开源解析包。
六.注意事项
尽量不要在重要的模块中使用解释器模式,否则维护会是一个很大的问题。在项目中可以使用shell、JRuby、Groovy等脚本语言来代替解释器模式,弥补Java编译型语言的不足。