定义:定义语言的文法,并且建立一个解释器来解释该语言中的句子。
类图:
说明:AbstractExpression表示抽象表达式,他生命声明一个抽象的解释操作,该接口为抽象语法树上所有的节点所共享;TerminalExpression表示终结符表达式,它实现与文法中的终结符相关联的解释操作,语言中每一个句子的每个终结符都属于该类的一个实例;NonterminalExpression表示非终结符表达式,他是吸纳了文法中的非终结符的解释操作,在解释过程中一般需要应用递归的方法是对句子进行处理;Context表示上下文,他包含了解释器之外的一些其他全局信息;Client表示客户端,它用于构建表示该文法定义的语言中的一个特定的句子的抽象语法树,该语法树有终结符表达式和非终结符报答是组成,并且Client负责调用解释操作。
优点:
解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。
缺点:
①解释器模式会引起类膨胀,每个语法都要生产一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。
②解释器模式采用递归调用方法,每个非终结符表达式只关心与自己有关的表达式,每个表达式需要直到最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断电的调试下去,知道最小的语法单元。
③效率问题,解释器模式由于使用了大量的循环和递归,效率诗歌不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。
适用环境:
①重复发生的问题可以使用解释器模式,例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,但是费终结符表达式就需要制定了。在这种情况下,可以通过程序来一劳永逸地解决该问题。
②一个简单语法需要解释的场景,为什么是简单?看看非中介表达式,文法规则越多,复杂度越高,而且类间还要进行递归调用,不是一般地复杂。想想看,多个类之间的调用你需要什么样的耐心和信心去排查问题。因此,解释器模式一般用来解析鼻尖标准的字符集,例如SQL语法分析,不过该部分逐渐被专用工具所取代。
实例场景:略。尽量不要在重要的模块中使用解释器模式,否则维护会是一个很大的问题,在项目中可以使用shell,JRuby、Groovy等脚本语言来代替解释器模式,弥补java编译型语言的不足。解释器模式在实际的系统开发中使用的非常少,因为它会引起效率、性能以及维护等问题,一般在大中型的框剪项目能够找到它的身影,比如一些数据分析工具、报表设计工具、科学计算工具等。