一、解释器模式定义
1.解释器模式是指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。是一种按照规定的语法(文法)进行解析的模式,属于行为型模式。
2.其核心思想是识别文法,构建解释。分离终结符号和非终结符号,提取出需要的信息
3.解释器模式的应用场景:
A.一些重复出现的问题可以用一种简单的语言来进行表达
B.一个简单语法需要解释的场景
二、解释器模式示例
1.解释器模式一般包含4种角色:
A.抽象表达式(Expression):负责定义一个解释方法interpret,交由具体子类进行具体解释
B.终结符表达式(TerminalExpression):实现文法中与终结符有关的解释操作。文法中的每一个终结符都有一个具体终结表达式与之相对应,比如公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符(R1,R2)
C.非终结符表达式(NonterminalExpression):实现文法中与非终结符有关的解释操作。文法中的每条规则都对应于一个非终结符表达式。非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,"+"就是非终结符,解析"+"的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
D.上下文环境类(Context):包含解释器之外的全局信息。它的任务一般是用来存放文法中各个终结符所对应的具体的值,比如R=R1+R2,给R1赋值100,给R2赋值200,这些信息需要存放到环境中
2.代码示例
1 public interface IArithmeticInterpreter {
2 int interpret();
3 }
4
5 public abstract class Interpreter implements IArithmeticInterpreter {
6
7 protected IArithmeticInterpreter left;
8 protected IArithmeticInterpreter right;
9
10 public Interpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
11 this.left = left;
12 this.right = right;
13 }
14 }
15
16 public class AddInterpreter extends Interpreter {
17
18 public AddInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
19 super(left, right);
20 }
21
22 public int interpret() {
23 return this.left.interpret() + this.right.interpret();
24 }
25 }
26
27 public class SubInterpreter extends Interpreter {
28 public SubInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
29 super(left, right);
30 }
31
32 public int interpret() {
33 return this.left.interpret() - this.right.interpret();
34 }
35 }
36
37 public class MultiInterpreter extends Interpreter {
38
39 public MultiInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
40 super(left,right);
41 }
42
43 public int interpret() {
44 return this.left.interpret() * this.right.interpret();
45 }
46
47 }
48
49 public class DivInterpreter extends Interpreter {
50
51 public DivInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
52 super(left,right);
53 }
54
55 public int interpret() {
56 return this.left.interpret() / this.right.interpret();
57 }
58
59 }
60
61 public class NumInterpreter implements IArithmeticInterpreter {
62 private int value;
63
64 public NumInterpreter(int value) {
65 this.value = value;
66 }
67
68
69 public int interpret() {
70 return this.value;
71 }
72 }
73
74 public class GPCalculator {
75 private Stack<IArithmeticInterpreter> stack = new Stack<IArithmeticInterpreter>();
76
77 public GPCalculator(String expression) {
78 this.parse(expression);
79 }
80
81 private void parse(String expression) {
82 String [] elements = expression.split(" ");
83 IArithmeticInterpreter leftExpr, rightExpr;
84
85 for (int i = 0; i < elements.length ; i++) {
86 String operator = elements[i];
87 if (OperatorUtil.isOperator(operator)){
88 leftExpr = this.stack.pop();
89 rightExpr = new NumInterpreter(Integer.valueOf(elements[++i]));
90 System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
91 this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr,operator));
92 System.out.println("应用运算符: " + operator);
93 }
94 else{
95 NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements[i]));
96 this.stack.push(numInterpreter);
97 System.out.println("入栈: " + numInterpreter.interpret());
98 }
99 }
100 }
101
102 public int calculate() {
103 return this.stack.pop().interpret();
104 }
105 }
106
107 public class OperatorUtil {
108
109 public static boolean isOperator(String symbol) {
110 return (symbol.equals("+") || symbol.equals("-") || symbol.equals("*"));
111 }
112
113 public static Interpreter getInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right, String symbol) {
114 if (symbol.equals("+")) {
115 return new AddInterpreter(left, right);
116 } else if (symbol.equals("-")) {
117 return new SubInterpreter(left, right);
118 } else if (symbol.equals("*")) {
119 return new MultiInterpreter(left, right);
120 } else if (symbol.equals("/")) {
121 return new DivInterpreter(left, right);
122 }
123 return null;
124 }
125 }
126
127 public class Test {
128
129 public static void main(String[] args) {
130 System.out.println("result: " + new GPCalculator("10 + 30").calculate());
131 System.out.println("result: " + new GPCalculator("10 + 30 - 20").calculate());
132 System.out.println("result: " + new GPCalculator("100 * 2 + 400 * 1 + 66").calculate());
133 }
134
135 }
3.解释器模式的优缺点
A.优点
a.扩展性强:在解释器模式中由于语法是由很多类表示的,当语法规则更改时,只需修改相应的非终结符表达式即可;若扩展语法时,只需添加相应非终结符类即可
b.增加了新的解释表达式的方式
c.易于实现文法:解释器模式对应的文法应当是比较简单且易于实现的,过于复杂的语法并不适合使用解释器模式