一、介绍:
1、定义:解释器(Interpreter)模式是一种对象的行为模式。给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
2、组成结构:
(1)AbstractExpression(抽象表达式):约定解释器的解释操作,主要是一个interpret()方法。这个接口作为抽象语法树中所有节点(即终结符表达式和非终结符表达式)所共享
- public abstract class AbstractExpression {
- public abstract void interpret(Context context);
- }
(2) TerminalExpression(终结符表达式):用来实现文法中和终结符相关的解释操作,不再包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的叶子对象,可以有多种终结符解释器。
- public class TerminalExpression extends AbstractExpression{
-
- @Override
- public void interpret(Context context) {
- System.out.println("终结符解释器");
- }
- }
(3)NonterminalExpression(非终结表达式):用来实现文法中和非终结符相关的解释操作,通常一个解释器对应一个语法规则,可以包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的组合对象,可以有多种非终结符解释器。公式R=R1+R2中,R1、R2为终结符表达式,+为非终结表达式(其后需要跟随一个终结符表达式)。
- public class NonterminalExpression extends AbstractExpression{
-
- @Override
- public void interpret(Context context) {
- System.out.println("非终结符解释器");
- }
- }
(4) Context类(包含解释器之外的一些全局信息):也称“上下文”,常用HashMap来代替,通常包含解释器之外的一些全局信息(解释器需要的数据,或是公共的功能)。
- public class Context {
- private String input;
- private String output;
-
- //Get、Set方法省略
- }
客户端,构建文法表示的抽象语法树(Abstract Syntax Tree),该抽象语法树由终结符表达式和非终结符表达式的实例装配而成),并调用解释操作interpret()方法。
- Context context = new Context();
- List
list = new ArrayList(); - list.add(new TerminalExpression());
- list.add(new NonterminalExpression());
- list.add(new TerminalExpression());
- list.add(new NonterminalExpression());
- for (AbstractExpression abstractExpression : list) {
- abstractExpression.interpret(context);
- }
3、适用场景:解释器模式似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个语言的文法。建议在以下情况中选用解释器模式: 当有一个语言需要解释执行,并且可以将语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式。
二、demo:
1、加减法计算器:
- //抽象表达式
- public interface AbstractExpression {
- int interprete(HashMap
var); - }
-
-
- //终结符表达式
- public class VarExpression implements AbstractExpression {
-
- private String key;
-
- public VarExpression(String key) {
- this.key = key;
- }
-
- public int interprete(HashMap
var) { - return (Integer) var.get(this.key);
- }
- }
-
-
-
- //加法符号 非终结表达式
- public class AddExpression implements AbstractExpression{
-
- private AbstractExpression left;
- private AbstractExpression right;
-
- public AddExpression(AbstractExpression left, AbstractExpression right) {
- this.left = left;
- this.right = right;
- }
-
- // 把左右两个表达式运算的结果加起来
- public int interprete(HashMap
var) { - return this.left.interprete(var) + this.right.interprete(var);
- }
- }
-
-
-
- //减法符号 非终结表达式
- public class SubExpression implements AbstractExpression{
-
- private AbstractExpression left;
- private AbstractExpression right;
-
- public SubExpression(AbstractExpression left, AbstractExpression right) {
- this.left = left;
- this.right = right;
- }
-
- // 把左右两个表达式运算的结果加起来
- public int interprete(HashMap
var) { - return this.left.interprete(var) - this.right.interprete(var);
- }
- }
- //封装计算器类
- public class Calculator {
-
- private AbstractExpression expression;
-
- public Calculator(String expStr) {
- // 定义一个堆栈,安排运算的先后顺序
- Stack<AbstractExpression> stack = new Stack<AbstractExpression>();
- // 表达式拆分为字符数组
- char[] charArray = expStr.toCharArray();
- // 运算
- AbstractExpression left = null;
- AbstractExpression right = null;
- for (int i = 0; i < charArray.length; i++) {
- switch (charArray[i]) {
- case '+':
- left = stack.pop();
- right = new VarExpression(String.valueOf(charArray[++i]));
- stack.push(new AddExpression(left, right));
- break;
-
- case '-':
- left = stack.pop();
- right = new VarExpression(String.valueOf(charArray[++i]));
- stack.push(new SubExpression(left, right));
- break;
- default: // 公式中的变量
- stack.push(new VarExpression(String.valueOf(charArray[i])));
- }
- }
- // 把运算结果抛出来
- this.expression = stack.pop();
- }
-
- // 计算结果
- public int calculate(HashMap<String, Integer> var) {
- return this.expression.interprete(var);
- }
- }
-
-
- //客户端
- public static void main(String args[]){
- // 构造运算元素的值列表
- HashMap<String, Integer> ctx = new HashMap<String, Integer>();
- ctx.put("a", 10);
- ctx.put("b", 20);
- ctx.put("c", 30);
- ctx.put("d", 40);
- ctx.put("e", 50);
- ctx.put("f", 60);
- Calculator calc = new Calculator("a+b-c");
- int result = calc.calculate(ctx);
- System.out.println("Result of a+b-c: " + result);
- calc = new Calculator("d-a-b+c");
- result = calc.calculate(ctx);
- System.out.println("Result of d-a-b+c: " + result);
- }
-
-
- 输出:
- Result of a+b-c: 0
- Result of d-a-b+c: 40