一、解釋器模式定義
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.易于實作文法:解釋器模式對應的文法應當是比較簡單且易于實作的,過于複雜的文法并不适合使用解釋器模式