解释器模式简绍

解释器模式(Interpreter Pattern)是一种软件设计模式,属于行为型模式之一。这种模式的主要目的是定义语言的语法表示,并且提供了一个解释器来处理这种表示。解释器模式可以用于解析语言或表达式等场合,特别是在编译器、解释器和自然语言处理中应用较多。

解释器模式的结构

解释器模式包含以下几个主要角色:

  • Abstract Expression(抽象表达式):
    • 这是所有表达式的公共接口或抽象类,它定义了所有非终端表达式和终端表达式所需要的方法,通常是interpret()方法。
  • Terminal Expression(终端表达式):
    • 实现了抽象表达式接口,负责处理文法中的文字符号,例如单词或数字等。
  • Non-Terminal Expression(非终端表达式):
    • 同样实现了抽象表达式接口,但它除了包含对文法符号的处理外,还包含对多个表达式的组合处理逻辑。
  • Context(环境):
    • 包含解释器之外的一些全局数据或者局部数据,供解释器解释过程中使用。
  • Client(客户端):
    • 构造一个完整的文法树,然后给定一个具体的上下文环境,最后调用解释方法。

优缺点

  • 解释器模式的优点
    • 增加了新的语句只需要增加新的终结符和非终结符表达式,不需要修改现有类。
  • 解释器模式的缺点
    • 对于复杂文法而言,类的数量会激增,导致系统难以维护。
    • 解释器模式递归使用,对于递归深度大的情况效率较低。

UML图

diagram-10464260208593657170.png

具体代码实现

Context 数据实体类,可以包含一些方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package InterpreterPatternModel;

public class TestContext {
private Integer a1;

private Integer a2;

private String a3;

public TestContext(Integer a1, Integer a2, String a3){
this.a1 = a1;
this.a2 = a2;
this.a3 = a3;
}

public String getA3() {
return a3;
}

public void setA3(String a3) {
this.a3 = a3;
}

public Integer getA1() {
return a1;
}

public void setA1(Integer a1) {
this.a1 = a1;
}

public Integer getA2() {
return a2;
}

public void setA2(Integer a2) {
this.a2 = a2;
}
}

Abstract Expression 创建接口方法

1
2
3
4
public interface AbstractExpression {
Integer interpret(TestContext context);

}

Terminal Expression 对数据简单处理

Terminal Expression 是解释器模式中的一种表达式类型,它表示文法中的最基本元素,这些元素不能再进一步分解。终端表达式通常对应于文法中的终端符号,如关键字、标识符、常量等。

  • 简单性:终端表达式是最基本的表达式,它不包含其他表达式。
  • 不可分解性:终端表达式代表的是文法中最基本的符号,不能再进一步拆解。
  • 具体实现:终端表达式通常是一个具体的类,它实现了抽象表达式接口,并提供了解释自身的方法。
    使用 switch 实现 加减乘除,对数据做直接处理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package InterpreterPatternModel;

    public class TestTerminalExpression implements AbstractExpression {

    @Override
    public Integer interpret(TestContext context) {
    switch (context.getA3()){
    case "+":
    return context.getA1() + context.getA2();
    case "-":
    return context.getA1() - context.getA2();
    case "*":
    return context.getA1() * context.getA2();
    case "/":
    return context.getA1() / context.getA2();
    default:
    return null;
    }
    }

    }

Non-Terminal Expression 同样实现抽象接口方法

Non-Terminal Expression 也是一种表达式类型,它代表了文法中的复合元素。这些元素由一个或多个终端表达式和其他非终端表达式组成。非终端表达式定义了如何组合这些表达式来解释更复杂的句子。

  • 组合性:非终端表达式可以包含一个或多个终端表达式或其他非终端表达式。
  • 递归性:非终端表达式通常通过递归调用其他表达式的 interpret 方法来解释更复杂的表达式。
  • 具体实现:非终端表达式也是一个具体的类,它实现了抽象表达式接口,并提供了解释自身的方法。
    对数据做复杂处理以及调用上面的优化,实现再次封装
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package InterpreterPatternModel;

    public class TestNonTerminalExpression implements AbstractExpression {

    private TestContext context;

    public TestNonTerminalExpression(Integer a1, Integer a2, String a3){
    this.context = new TestContext(a1, a2, a3);
    }

    public Integer exec(){
    return this.interpret(context);
    }

    @Override
    public Integer interpret(TestContext context) {
    TestTerminalExpression testTerminalExpression = new TestTerminalExpression();
    return testTerminalExpression.interpret(context);
    }
    }

Client(客户端) 调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package InterpreterPatternModel;

public class TestClient {

public static void exec(){
TestTerminalExpression testTerminalExpression = new TestTerminalExpression();
Integer interpret = testTerminalExpression.interpret(new TestContext(1, 2, "*"));
System.out.println(interpret);
TestNonTerminalExpression nonTerminal = new TestNonTerminalExpression(10, 2, "+");
Integer exec = nonTerminal.exec();
System.out.println(exec);
Integer interpret1 = nonTerminal.interpret(new TestContext(new TestNonTerminalExpression(1, 2, "*").exec(), new TestNonTerminalExpression(10, 2, "-").exec(), "+"));
System.out.println(interpret1);
}
}

通过Terminal Expression(终端表达式) 和 Non-Terminal Expression(非终端表达式)
这两种表达式类型的组合,解释器模式能够构建出一个能够解析并解释复杂文法的解释器。这种模式使得添加新的语法规则变得相对容易,因为只需添加新的终端和非终端表达式即可。但是,随着文法复杂度的增加,非终端表达式的数量也会增加,这可能导致类的数量激增,从而增加了系统的复杂性和维护难度。