經過解釋器模式來實現四則運算,如計算 a + b + c 的值,具體要求
1)先輸入表達式的形式,好比 a + b + c + d + e,要求表達式的字母不能重複
2)在分別輸入a,b,c,d,e的值
3)最後求出結果java
1)編寫一個方法,接收表達式的形式,而後根據用戶輸入的數值進行解析,獲得結果
2)問題分析 :若是加入新的運算符,好比 */ (等等,不利於擴展,另外讓一個方法來解析會形成程序結構混亂,不夠清晰。
3)解決方案:能夠考慮使用解釋器模式,即 :表達式 -》解釋器能夠有多種 -》結果正則表達式
1)在編譯原理中,一個算術表達式經過詞法分析器造成詞法單元,然後這些詞法單元再經過詞法分析器構建語法分析樹,最終造成一顆抽象的語法分析樹。這裏的詞法分析器和語法分析器均可以看作是解釋器。
2)解釋器模式(Interpreter Pattern):是指給定一個語言表達式,定義它的文法的一種表示,並定義一個解釋器,使用該解釋器來解釋語言中的句子(表達式)
3)應用場景
應用能夠將一個須要解釋執行的語言中的句子表示爲一個抽象語法樹
一些重複出現的問題能夠用一種簡單的語言來表達
一個簡單語法須要解釋的場景
4)這樣的例子還有,好比編譯器、運算表達式計算、正則表達式、機器人等。
1)Context :是環境角色,含有解釋器以外的全局信息。
2)AbstractExpression :抽象表達式,聲明一個抽象的解釋操做,這個方法爲抽象語法樹中全部的節點所共享。
3)TerminalExpression :爲終結符表達式,實現與文法中的終結符相關的解釋操做。
4)NonTermialExpression :爲非終結符表達式,爲文法中的非終結符實現解釋操做。
5)說明 :輸入Context 和TerminalExpression 信息經過Client 輸入便可。express
1)應用實例要求
經過解釋器模式來實現四則運算,如計算a + b + c 的值。
設計模式
package com.example.demo.interpreter; import java.util.HashMap; /** * 加法解釋器 * @author Administrator * */ public class AddExpression extends SymbolExpression{ public AddExpression(Expression left, Expression right) { super(left, right); } //處理相加 //var 仍然是 {a=10,b=20}.. //一會咱們 debug 源碼,就 ok public int interpreter(HashMap<String, Integer> var) { //super.left.interpreter(var) : 返回 left 表達式對應的值 a = 10 //super.right.interpreter(var): 返回 right 表達式對應值 b = 20 return super.left.interpreter(var) + super.right.interpreter(var); } } package com.example.demo.interpreter; import java.util.HashMap; import java.util.Stack; public class Calculator { // 定義表達式 private Expression expression; // 構造函數傳參,並解析 public Calculator(String expStr) { // expStr = a+b // 安排運算前後順序 Stack<Expression> stack = new Stack<>(); // 表達式拆分紅字符數組 char[] charArray = expStr.toCharArray();// [a, +, b] Expression left = null; Expression right = null; //遍歷咱們的字符數組, 即遍歷 [a, +, b] //針對不一樣的狀況,作處理 for (int i = 0; i < charArray.length; i++) { switch (charArray[i]) { case '+': // left = stack.pop();// 從 stack 取出 left => "a" right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表達式 "b" stack.push(new AddExpression(left, right));// 而後根據獲得 left 和 right 構建 AddExpresson 加入stack break; case '-': // left = stack.pop(); right = new VarExpression(String.valueOf(charArray[++i])); stack.push(new SubExpression(left, right)); break; default: //若是是一個 Var 就建立要給 VarExpression 對象,並 push 到 stack stack.push(new VarExpression(String.valueOf(charArray[i]))); break; } } //當遍歷完整個 charArray 數組後,stack 就獲得最後 Expression this.expression = stack.pop(); } public int run(HashMap<String, Integer> var) { // 最後將表達式 a+b 和 var = {a=10,b=20} //而後傳遞給 expression 的 interpreter // 進行解釋執行 return this.expression.interpreter(var); } } package com.example.demo.interpreter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; public class Client { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // TODO Auto-generated method stub String expStr = getExpStr(); // a+b HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20} Calculator calculator = new Calculator(expStr); System.out.println("運算結果:" + expStr + "=" + calculator.run(var)); } // 得到表達式 public static String getExpStr() throws IOException { System.out.print("請輸入表達式:"); return (new BufferedReader(new InputStreamReader(System.in))).readLine(); } // 得到值映射 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; } } package com.example.demo.interpreter; import java.util.HashMap; /** * 抽象類表達式,經過 HashMap 鍵值對, 能夠獲取到變量的值 * * @author Administrator * */ public abstract class Expression { // a + b - c // 解釋公式和數值, key 就是公式(表達式) 參數[a,b,c], value 就是就是具體值 // HashMap {a=10, b=20} public abstract int interpreter(HashMap<String, Integer> var); } package com.example.demo.interpreter; import java.util.HashMap; public class SubExpression extends SymbolExpression{ public SubExpression(Expression left, Expression right) { super(left, right); } //求出 left 和 right 表達式相減後的結果 public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) - super.right.interpreter(var); } } package com.example.demo.interpreter; import java.util.HashMap; /** * 抽象運算符號解析器 這裏,每一個運算符號,都只和本身左右兩個數字有關係, * 但左右兩個數字有可能也是一個解析的結果,不管何種類型,都是 Expression 類的實現類 * * @author Administrator * */ public class SymbolExpression extends Expression{ protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right; } //由於 SymbolExpression 是讓其子類來實現,所以 interpreter 是一個默認實現 @Override public int interpreter(HashMap<String, Integer> var) { // TODO Auto-generated method stub return 0; } } package com.example.demo.interpreter; import java.util.HashMap; /** * 變量的解釋器 * @author Administrator * */ public class VarExpression extends Expression { private String key; // key=a,key=b,key=c public VarExpression(String key) { this.key = key; } // var 就是{a=10, b=20} // interpreter 根據 變量名稱,返回對應值 @Override public int interpreter(HashMap<String, Integer> var) { return var.get(this.key); } }
1)當有一個語言須要解釋執行,可將該語言中的句子表示爲一個抽象語法樹,就能夠考慮使用解釋器模式,讓程序具備良好的擴展性。
2)應用場景 :編譯器、運算表達式計算、正則表達式、機器人等。
3)使用解釋器可能帶來的問題 :解釋器模式會引發類膨脹、解釋器模型採用遞歸調用方法,將會致使調試很是複雜、效率可能下降。數組