alexpdh's blog

Java设计模式(二十四):解释器模式

解释器模式(Interpreter Pattern)

解释器模式(Interpreter Pattern):属于对象的行为模式。给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。


解释器模式UML图

interpreter-pattern.jpg


解释器模式涉及的角色

抽象表达式(AbstractExpression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称做解释操作。
终结符表达式(TerminalExpression)角色:实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
非终结符表达式(NonTerminalExpression )角色:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。
环境(Context)角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。


示例代码

环境类 InterpreterContext

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
package com.example.interpreterPattern;
/**
* 解释器模式:环境类
*
* @author pengdh
* @date: 2017-08-13 23:56
*/
public class InterpreterContext {
private String input;
private String output;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
}

抽象表达式类 AbstractExpresstion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.interpreterPattern;
/**
* 解释器模式:抽象表达式类
*
* @author pengdh
* @date: 2017-08-13 23:57
*/
public abstract class AbstractExpresstion {
/**
* 以给定的环境为准,解释给定的任何一个表达式
* @param context
*/
public abstract void interpret(InterpreterContext context);
}

终结符表达式类 TerminalExpression

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.interpreterPattern;
/**
* 解释器模式:终结符表达式类
*
* @author pengdh
* @date: 2017-08-14 0:01
*/
public class TerminalExpression extends AbstractExpresstion {
@Override
public void interpret(InterpreterContext context) {
System.out.println("终端解释器");
}
}

非终结表达式类 NonTerminalExpresstion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.interpreterPattern;
/**
* 解释器模式:非终结表达式类
*
* @author pengdh
* @date: 2017-08-14 0:04
*/
public class NonTerminalExpresstion extends AbstractExpresstion {
@Override
public void interpret(InterpreterContext context) {
System.out.println("非终端解释器");
}
}

客户端测试类 InterpreterPatternTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.interpreterPattern;
import java.util.ArrayList;
import java.util.List;
/**
* 解释器模式:客户端测试类
*
* @author pengdh
* @date: 2017-08-14 0:05
*/
public class InterpreterPatternTest {
public static void main(String[] args) {
InterpreterContext context = new InterpreterContext();
List<AbstractExpresstion> list = new ArrayList<AbstractExpresstion>();
list.add(new TerminalExpression());
list.add(new NonTerminalExpresstion());
list.add(new TerminalExpression());
for (AbstractExpresstion exp : list) {
exp.interpret(context);
}
}
}

解释器模式优点

很容易改变和扩展文法,因为解释器模式使用类来表示文法规则,你可以使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。


解释器模式缺点

解释器模式为文法中的每一条规则至少定义一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术来处理。


参考文献

alexpdh wechat
欢迎扫一扫关注 程序猿pdh 公众号!