? **請注意!請注意!!!**今天講給大家講解非常“有用”的設計模式,解釋器模式!!!
? 設計模式有三大種類,一種是創建型模式,一種是結構型模式,最后一種是行為性模式,那么解釋器模式屬于哪一種呢?帶領大家一起來了解學習解釋器模式!
? 本次介紹圍繞著以下五點展開。什么是解釋器模式?用來做什么?怎么做?有哪些優點?有哪些不足?
? 解釋器模式顧名思義,就是用來定義和解釋。
? 給定一種特定語言,這個語言有特定的文法,解釋器可以解釋這個語言中的句子含義。即解釋器提供一種語言,如java,同時它也提供一種手段去解析java語言寫出來的代碼。
? 大家可能也會想到這就是類似編譯原理,一個算術表達式要經過詞法分析,語法分析,構建語法樹啥的;還有正則表達式;SQL解析,編譯器等等,其實都是解析式模式的一種實現。
? 那怎么做?一個是說要有像編譯原理中的終結符和非終結符,構建一顆語法樹。同時需要有一個環境類,來管理輸入和輸出。
? 這里我們舉一個例子,輸入一個表達式a+b-c+d-e,同時給這5個變量賦值,計算出它的值。那么使用解釋器模式要如何實現?
? 我們為解釋器定義一個抽象解釋類Expression,所有的流轉通過interpreter方法實現。
? 上下文管理輸入輸出使用一個HashMap
去實現。
? 定義符號解釋類SymbolExpression
,加法解釋類AddExpreesion
,減法解釋類SubExpression
。
類圖:
具體代碼實現:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
public abstract class Expression { // map中攜帶了表達式中的變量名(key) 和 對應的值(value) public abstract int interpreter(Map<String, Integer> var); } public class VarExpression extends Expression { // 表達式中對應的變量名 String key; public VarExpression(String var) { this .key = var; } @Override public int interpreter(Map<String, Integer> var) { return var.get(key); } } public class SymbolExpression extends Expression { // +或-符號 左右兩邊的表達式 Expression var1; Expression var2; public SymbolExpression(Expression var1, Expression var2) { this .var1 = var1; this .var2 = var2; } @Override public int interpreter(Map<String, Integer> var) { // 實現抽象方法 // 該類不需要用到該方法 默認返回0 return 0 ; } } public class AddExpression extends SymbolExpression { public AddExpression(Expression var1, Expression var2) { super (var1, var2); } @Override public int interpreter(Map<String, Integer> var) { return var1.interpreter(var) + var2.interpreter(var); } } public class SubExpression extends SymbolExpression { public SubExpression(Expression var1, Expression var2) { super (var1, var2); } @Override public int interpreter(Map<String, Integer> var) { return var1.interpreter(var) - var2.interpreter(var); } } public class Calculator { // 表達式 private Expression expression; // 解析出表達式 public Calculator(String expStr) { Stack<Expression> stack = new Stack<>(); Expression left, right = null ; char [] expStrCharArray = expStr.toCharArray(); for ( int i = 0 ; i < expStrCharArray.length; i++) { switch (expStrCharArray[i]) { case '+' : // 加法運算 獲取左邊表達式 右邊數值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push( new AddExpression(left, right)); break ; case '-' : // 減法運算 獲取左邊表達式 右邊數值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push( new SubExpression(left, right)); break ; default : // 表達式中的變量 stack.push( new VarExpression(String.valueOf(expStrCharArray[i]))); break ; } } // 最后會獲得被Expression包裝起來的一個表達式 this .expression = stack.pop(); } // 計算結果 public int run(Map<String, Integer> var) { return this .expression.interpreter(var); } } public class Client { public static void main(String[] args) throws IOException { String expStr = getExpStr(); Map<String, Integer> var = getValue(expStr); Calculator calculator = new Calculator(expStr); System.out.println( "運算結果:" + expStr + "=" + calculator.run(var)); } //獲得表達式 public static String getExpStr() { return "a+b-c+d-e" ; } //獲得值映射 public static HashMap<String, Integer> getValue(String expStr) throws IOException { HashMap<String, Integer> map = new HashMap<>(); for ( char ch : expStr.toCharArray()) { if (ch != '+' && ch != '-' ) { if (! map.containsKey(String.valueOf(ch))) { System.out.print( "請輸入" + String.valueOf(ch) + "的值:" ); String in = ( new BufferedReader( new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch), Integer.valueOf(in)); } } } return map; } } |
結果
/*
請輸入a的值:1
請輸入b的值:3
請輸入c的值:5
請輸入d的值:7
請輸入e的值:9
運算結果:a+b-c+d-e=-3
*/
? 或許看代碼會有點云里霧里,希望大家能手動敲一遍,或許會對整個過程有更進一步的理解,在編碼的同時不斷思考,提升自我。
? 很容易發現解釋器模式是屬于行為性模式的一種,這種模式更關注對象之間的通信。
? 解釋器模式優點,結構清晰,可拓展性好。但也有缺點,一般用在比較底層場景,平常敲代碼可使用的場景比較少,并且解釋器模式采用的是遞歸的方式,當語言比較長,性能不高;同時如果文法比較復雜,也需要更多的相應解釋類。
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!
原文鏈接:https://blog.csdn.net/KnightHONG/article/details/120693753