1. 模式定义⭐️🔴

解释器模式(Interpreter Pattern):是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

第一步:我们需要将待解决的问题,提取出规则,抽象为一种“语言”。即文法(语法)规则。比如加减法运算,规则为:由数值和+-符号组成的合法序列,“1+3-2” 就是这种语言的句子。
第二步:解析出像“1+3-2” 这样语句的含义,即通过一定的表现形式来表达语句的含义,比如抽象语法树(AbstractSyntaxTree,AST),或简称语法树(Syntax tree)就是一种抽象表示,是用树形来表示符合文法规则的句子。❕%%
0717-🏡⭐️◼️解释器模式的概念是什么🔜📝 将我们待解决的问题,比如已经变成了一段表达式,我们再抽象成文法表示,然后给出一个解释器,通过一定的变现形式,比如抽象语法树,来表示出该类表达式所表示的含义◼️⭐️-point-202301300717%%

2. 模式结构

2.1. 模式角色

  • Context环境角色:含有解释器之外的全局信息
  • AbstractExpression抽象表达式:声明一个抽象的解释操作,该方法为抽象语法树中所有节点共享
  • TerminalExpression终结符表达式:实现与文法中终结符相关的解释操作
  • NonTerminalExpression非终结符表达式:实现与文法中非终结符相关的解释操作

2.2. UML⭐️🔴

image.png

2.3. 实现逻辑

3. 案例分析

3.1. 设计实现加减法

3.1.1. UML

3.1.2. 实现逻辑⭐️🔴

继承+聚合

  1. Context聚合并集合管理Variable变量类
  2. 终结符表达式类(Variable)、非终结符表达式类(Plus)、非终结符表达式类(Minus)继承抽象表达式类(AbstractExpression)
  3. 因为是非终结,所以非终结符表达式类(Plus)、非终结符表达式类(Minus)还聚合抽象表达式类(AbstractExpression)为其左右符号变量

3.1.3. Demo

[[pages/002-schdule/001-Arch/001-Subject/013-DemoCode/design_patterns/src/main/java/com/itheima/pattern/interpreter/AbstractExpression.java]]

4. 适用场景

  • 当语言的文法较为简单,且执行效率不是关键问题时,因为存在递归解释现象。
  • 当问题重复出现,且可以用一种简单的语言来进行表达时。
  • 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。

5. 优缺点

1. 优点:

  • 易于改变和扩展文法。
    由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。

  • 实现文法较为容易。
    在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。

  • 增加新的解释表达式较为方便。
    如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 “开闭原则”

2. 缺点:

  • 对于复杂文法难以维护。
    在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。

  • 执行效率较低。
    由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

6. JDK源码分析

6.1. Spring框架中SpelExpressionParser

image.png

角色及职责

  • Expression表达式接口
  • 下面有不同表达式实现类,比如SpelExpressionLiteralExpressionCompositeStringExpression
  • 使用时,根据创建解释器对象的不同,返回不同的Expression对象

7. 实战经验

  • 1)当有一个语言需要解释执行,可将该语言中的句子表示为一个抽象语法树,就可以考虑使用解释器模式,让程序具有良好的扩展性
  • 2)应用场景:编译器、运算表达式计算、正则表达式、机器人等
  • 3)使用解释器可能带来的问题:解释器模式会引起类膨胀、解释器模式采用递归调用方法,将会导致调试非常复杂、效率可能降低

8. 参考与感谢

设计模式-2、设计模式及设计原则