淺談Java解釋器模式
**請注意!請注意?。?!**今天講給大家講解非?!?strong>有用”的設(shè)計(jì)模式,解釋器模式?。?!
設(shè)計(jì)模式有三大種類,一種是創(chuàng)建型模式,一種是結(jié)構(gòu)型模式,最后一種是行為性模式,那么解釋器模式屬于哪一種呢?帶領(lǐng)大家一起來了解學(xué)習(xí)解釋器模式!
本次介紹圍繞著以下五點(diǎn)展開。什么是解釋器模式?用來做什么?怎么做?有哪些優(yōu)點(diǎn)?有哪些不足?
解釋器模式顧名思義,就是用來定義和解釋。
給定一種特定語言,這個語言有特定的文法,解釋器可以解釋這個語言中的句子含義。即解釋器提供一種語言,如java,同時它也提供一種手段去解析java語言寫出來的代碼。
大家可能也會想到這就是類似編譯原理,一個算術(shù)表達(dá)式要經(jīng)過詞法分析,語法分析,構(gòu)建語法樹啥的;還有正則表達(dá)式;SQL解析,編譯器等等,其實(shí)都是解析式模式的一種實(shí)現(xiàn)。
那怎么做?一個是說要有像編譯原理中的終結(jié)符和非終結(jié)符,構(gòu)建一顆語法樹。同時需要有一個環(huán)境類,來管理輸入和輸出。
這里我們舉一個例子,輸入一個表達(dá)式a+b-c+d-e,同時給這5個變量賦值,計(jì)算出它的值。那么使用解釋器模式要如何實(shí)現(xiàn)?
我們?yōu)榻忉屍鞫x一個抽象解釋類Expression,所有的流轉(zhuǎn)通過interpreter方法實(shí)現(xiàn)。
上下文管理輸入輸出使用一個HashMap
去實(shí)現(xiàn)。
定義符號解釋類SymbolExpression
,加法解釋類AddExpreesion
,減法解釋類SubExpression
。
類圖:
具體代碼實(shí)現(xiàn):
public abstract class Expression { // map中攜帶了表達(dá)式中的變量名(key) 和 對應(yīng)的值(value) public abstract int interpreter(Map<String, Integer> var); } public class VarExpression extends Expression { // 表達(dá)式中對應(yīng)的變量名 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 { // +或-符號 左右兩邊的表達(dá)式 Expression var1; Expression var2; public SymbolExpression(Expression var1, Expression var2) { this.var1 = var1; this.var2 = var2; } @Override public int interpreter(Map<String, Integer> var) { // 實(shí)現(xiàn)抽象方法 // 該類不需要用到該方法 默認(rèn)返回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 { // 表達(dá)式 private Expression expression; // 解析出表達(dá)式 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 '+':// 加法運(yùn)算 獲取左邊表達(dá)式 右邊數(shù)值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push(new AddExpression(left, right)); break; case '-':// 減法運(yùn)算 獲取左邊表達(dá)式 右邊數(shù)值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push(new SubExpression(left, right)); break; default:// 表達(dá)式中的變量 stack.push(new VarExpression(String.valueOf(expStrCharArray[i]))); break; } } // 最后會獲得被Expression包裝起來的一個表達(dá)式 this.expression = stack.pop(); } // 計(jì)算結(jié)果 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("運(yùn)算結(jié)果:" + expStr + "=" + calculator.run(var)); } //獲得表達(dá)式 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; } }
結(jié)果
/*
請輸入a的值:1
請輸入b的值:3
請輸入c的值:5
請輸入d的值:7
請輸入e的值:9
運(yùn)算結(jié)果:a+b-c+d-e=-3
*/
或許看代碼會有點(diǎn)云里霧里,希望大家能手動敲一遍,或許會對整個過程有更進(jìn)一步的理解,在編碼的同時不斷思考,提升自我。
很容易發(fā)現(xiàn)解釋器模式是屬于行為性模式的一種,這種模式更關(guān)注對象之間的通信。
解釋器模式優(yōu)點(diǎn),結(jié)構(gòu)清晰,可拓展性好。但也有缺點(diǎn),一般用在比較底層場景,平常敲代碼可使用的場景比較少,并且解釋器模式采用的是遞歸的方式,當(dāng)語言比較長,性能不高;同時如果文法比較復(fù)雜,也需要更多的相應(yīng)解釋類。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
java實(shí)現(xiàn)清理DNS Cache的方法
這篇文章主要介紹了java實(shí)現(xiàn)清理DNS Cache的方法,分析了幾種常用的清理方法,并給出了反射清理的完整實(shí)例,具有一定參考借鑒價值,需要的朋友可以參考下2015-01-01Java?Map.values()方法之如何獲取Map集合中的所有鍵值對象
這篇文章主要介紹了Java?Map.values()方法之如何獲取Map集合中的所有鍵值對象問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03Spring定時任務(wù)輪詢本地?cái)?shù)據(jù)庫實(shí)現(xiàn)過程解析
這篇文章主要介紹了Spring定時任務(wù)輪詢本地?cái)?shù)據(jù)庫實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01詳解SpringBoot下文件上傳與下載的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot下文件上傳與下載的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法
本篇文章主要介紹了spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01Java中增強(qiáng)for循環(huán)的實(shí)現(xiàn)原理和坑詳解
增強(qiáng)的for循環(huán)是在傳統(tǒng)的for循環(huán)中增加的強(qiáng)大的迭代功能的循環(huán),是在jdk1.5之后提出來的。下面這篇文章主要給大家介紹了關(guān)于Java中增強(qiáng)for循環(huán)的實(shí)現(xiàn)原理和坑的相關(guān)資料,需要的朋友可以參考下2018-04-04