设计模式 解释器模式(Interpreter Pattern)
文章目录
- 解释器模式简绍
- 解释器模式的结构
- 优缺点
- UML图
- 具体代码实现
- Context 数据实体类,可以包含一些方法
- Abstract Expression 创建接口方法
- Terminal Expression 对数据简单处理
- Non-Terminal Expression 同样实现抽象接口方法
- Client(客户端) 调用方法
解释器模式简绍
解释器模式(Interpreter Pattern)是一种软件设计模式,属于行为型模式之一。这种模式的主要目的是定义语言的语法表示,并且提供了一个解释器来处理这种表示。解释器模式可以用于解析语言或表达式等场合,特别是在编译器、解释器和自然语言处理中应用较多。
解释器模式的结构
解释器模式包含以下几个主要角色:
- Abstract Expression(抽象表达式):
- 这是所有表达式的公共接口或抽象类,它定义了所有非终端表达式和终端表达式所需要的方法,通常是interpret()方法。
- Terminal Expression(终端表达式):
- 实现了抽象表达式接口,负责处理文法中的文字符号,例如单词或数字等。
- Non-Terminal Expression(非终端表达式):
- 同样实现了抽象表达式接口,但它除了包含对文法符号的处理外,还包含对多个表达式的组合处理逻辑。
- Context(环境):
- 包含解释器之外的一些全局数据或者局部数据,供解释器解释过程中使用。
- Client(客户端):
- 构造一个完整的文法树,然后给定一个具体的上下文环境,最后调用解释方法。
优缺点
- 解释器模式的优点
- 增加了新的语句只需要增加新的终结符和非终结符表达式,不需要修改现有类。
- 解释器模式的缺点
- 对于复杂文法而言,类的数量会激增,导致系统难以维护。
- 解释器模式递归使用,对于递归深度大的情况效率较低。
UML图
具体代码实现
Context 数据实体类,可以包含一些方法
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 创建接口方法
public interface AbstractExpression {
Integer interpret(TestContext context);
}
Terminal Expression 对数据简单处理
Terminal Expression 是解释器模式中的一种表达式类型,它表示文法中的最基本元素,这些元素不能再进一步分解。终端表达式通常对应于文法中的终端符号,如关键字、标识符、常量等。
- 简单性:终端表达式是最基本的表达式,它不包含其他表达式。
- 不可分解性:终端表达式代表的是文法中最基本的符号,不能再进一步拆解。
- 具体实现:终端表达式通常是一个具体的类,它实现了抽象表达式接口,并提供了解释自身的方法。
使用 switch 实现 加减乘除,对数据做直接处理
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 方法来解释更复杂的表达式。
- 具体实现:非终端表达式也是一个具体的类,它实现了抽象表达式接口,并提供了解释自身的方法。
对数据做复杂处理以及调用上面的优化,实现再次封装
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(客户端) 调用方法
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(非终端表达式)
这两种表达式类型的组合,解释器模式能够构建出一个能够解析并解释复杂文法的解释器。这种模式使得添加新的语法规则变得相对容易,因为只需添加新的终端和非终端表达式即可。但是,随着文法复杂度的增加,非终端表达式的数量也会增加,这可能导致类的数量激增,从而增加了系统的复杂性和维护难度。