# 解释器模式Interpreter
阅读量  loading 
 # 一、概念
# 1、定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
# 2、扩展
为了解释一种语言,而为语言创建的解释器
# 3、类型
行为型
# 4、适用场景
某个特定类型问题发生频率足够高
# 5、优点
语法由很多类表示,容易改变及扩展次“语言”
# 6、缺点
当语法规则数目太多时,增加了系统复杂度
# 7、相关设计模式
- 解释器模式和适配器模式
 
适配器模式不需要预先知道需要适配的规则,而对于解释器模式需要把规则写好,根据规则进行解释。
# 二、应用
首先声明一个接口,也是解释器模式中最终要的部分:
public interface Interpreter {
    int interpret();
}
 1
2
3
4
2
3
4
它包含一个解释的方法。
创建一个加法解释器:
public class AddInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;
    public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }
    @Override
    public int interpret() {
        return firstExpression.interpret() + secondExpression.interpret();
    }
    @Override
    public String toString() {
        return "+";
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
乘法解释器:
public class MultiInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;
    public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }
    @Override
    public int interpret() {
        return firstExpression.interpret() * secondExpression.interpret();
    }
    @Override
    public String toString() {
        return "*";
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
数字解释器:
public class NumberInterpreter implements Interpreter {
    private int number;
    public NumberInterpreter(int number) {
        this.number = number;
    }
    public NumberInterpreter(String number) {
        this.number = Integer.parseInt(number);
    }
    @Override
    public int interpret() {
        return number;
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这个类接受两种类型的构造参数,通过 interpret() 方法返回 int 类型。
在创建一个解释器的类,他有一个运算的方法:
public class ExpressionParser {
    private Stack<Interpreter> stack = new Stack<>();
    public int parse(String str) {
        String[] strItemArray = str.split(" ");
        for (String symbol : strItemArray) {
            if (!OperatorUtil.isOperator(symbol)) {
                Interpreter numberExpression = new NumberInterpreter(symbol);
                stack.push(numberExpression);
                System.out.println(String.format("入栈:%d", numberExpression.interpret()));
            } else {
                // 是运算符可以计算
                Interpreter firstExpression = stack.pop();
                Interpreter secondExpression = stack.pop();
                System.out.println(String.format("出栈:%d 和 %d",
                        firstExpression.interpret(), secondExpression.interpret()));
                Interpreter operator = OperatorUtil.getExpressionObject(firstExpression, secondExpression, symbol);
                System.out.println(String.format("应用运算符:%s", operator));
                int result = operator.interpret();
                NumberInterpreter resultExpression = new NumberInterpreter(result);
                stack.push(resultExpression);
                System.out.println(String.format("阶段结果入栈:%d", resultExpression.interpret()));
            }
        }
        return stack.pop().interpret();
    }
}
 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
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
里面用到的一个工具类:
public class OperatorUtil {
    public static boolean isOperator(String symbol) {
        return (symbol.equals("+") || symbol.equals("*"));
    }
    public static Interpreter getExpressionObject(Interpreter firstExpression, Interpreter secondExpression,
                                                  String symbol) {
        if (symbol.equals("+")) {
            return new AddInterpreter(firstExpression, secondExpression);
        } else if (symbol.equals("*")) {
            return new MultiInterpreter(firstExpression, secondExpression);
        }
        return null;
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
测试类:
public class Test {
    public static void main(String[] args) {
        String inputStr = "6 100 11 + *";
        ExpressionParser expressionParser = new ExpressionParser();
        int result = expressionParser.parse(inputStr);
        System.out.println("解释器计算结果:" + result);
    }
}
 1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
执行结果:
入栈:6
入栈:100
入栈:11
出栈:11 和 100
应用运算符:111
阶段结果入栈:111
出栈:111 和 6
应用运算符:666
阶段结果入栈:666
解释器计算结果:666
 1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
类图:

# 三、源码中的应用
# 1、Pattern
正则表达式就是通过 Pattern 解析出来的。
# 2、ExpressionParser
org.springframework.expression 包下的 ExpressionParser 用来解析 EL 语法,它有3个实现类:InternalSpelExpressionParser、SpelExpressionParser、TemplateAwareExpressionParser,下面是演示它的使用方法:
public class SpringTest {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
        int result = (int) expression.getValue();
        System.out.println(result);
    }
}
 1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
执行结果:
666
 1
← 策略模式Strategy 观察者模式 →