淺談Java解釋器模式
**請注意!請注意!??!**今天講給大家講解非常“有用”的設(shè)計模式,解釋器模式!?。?/p>
設(shè)計模式有三大種類,一種是創(chuàng)建型模式,一種是結(jié)構(gòu)型模式,最后一種是行為性模式,那么解釋器模式屬于哪一種呢?帶領(lǐng)大家一起來了解學(xué)習(xí)解釋器模式!
本次介紹圍繞著以下五點展開。什么是解釋器模式?用來做什么?怎么做?有哪些優(yōu)點?有哪些不足?
解釋器模式顧名思義,就是用來定義和解釋。
給定一種特定語言,這個語言有特定的文法,解釋器可以解釋這個語言中的句子含義。即解釋器提供一種語言,如java,同時它也提供一種手段去解析java語言寫出來的代碼。
大家可能也會想到這就是類似編譯原理,一個算術(shù)表達(dá)式要經(jīng)過詞法分析,語法分析,構(gòu)建語法樹啥的;還有正則表達(dá)式;SQL解析,編譯器等等,其實都是解析式模式的一種實現(xiàn)。
那怎么做?一個是說要有像編譯原理中的終結(jié)符和非終結(jié)符,構(gòu)建一顆語法樹。同時需要有一個環(huán)境類,來管理輸入和輸出。
這里我們舉一個例子,輸入一個表達(dá)式a+b-c+d-e,同時給這5個變量賦值,計算出它的值。那么使用解釋器模式要如何實現(xiàn)?
我們?yōu)榻忉屍鞫x一個抽象解釋類Expression,所有的流轉(zhuǎn)通過interpreter方法實現(xiàn)。
上下文管理輸入輸出使用一個HashMap去實現(xiàn)。
定義符號解釋類SymbolExpression,加法解釋類AddExpreesion,減法解釋類SubExpression。
類圖:

具體代碼實現(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) {
// 實現(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 '+':// 加法運算 獲取左邊表達(dá)式 右邊數(shù)值
left = stack.pop();
right = new VarExpression(String.valueOf(expStrCharArray[++i]));
stack.push(new AddExpression(left, right));
break;
case '-':// 減法運算 獲取左邊表達(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();
}
// 計算結(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("運算結(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
運算結(jié)果:a+b-c+d-e=-3
*/
或許看代碼會有點云里霧里,希望大家能手動敲一遍,或許會對整個過程有更進(jìn)一步的理解,在編碼的同時不斷思考,提升自我。
很容易發(fā)現(xiàn)解釋器模式是屬于行為性模式的一種,這種模式更關(guān)注對象之間的通信。
解釋器模式優(yōu)點,結(jié)構(gòu)清晰,可拓展性好。但也有缺點,一般用在比較底層場景,平常敲代碼可使用的場景比較少,并且解釋器模式采用的是遞歸的方式,當(dāng)語言比較長,性能不高;同時如果文法比較復(fù)雜,也需要更多的相應(yīng)解釋類。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Intellij Idea部署OpenCV 4.0.0環(huán)境
這篇文章主要為大家詳細(xì)介紹了Intellij Idea部署OpenCV 4.0.0環(huán)境,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07
Java的四種常見線程池及Scheduled定時線程池實現(xiàn)詳解
這篇文章主要介紹了Java的四種常見線程池及Scheduled定時線程池實現(xiàn)詳解,在Java中,我們可以通過Executors類來創(chuàng)建ScheduledThreadPool,Executors類提供了幾個靜態(tài)方法來創(chuàng)建不同類型的線程池,包括ScheduledThreadPool,需要的朋友可以參考下2023-09-09
springboot使用log4j2異步日志提升性能的實現(xiàn)方式
這篇文章主要介紹了springboot使用log4j2異步日志提升性能,異步日志實現(xiàn)方式:將日志存入一個單獨的隊列中,有一個單獨的線程從隊列中獲取日志并寫入磁盤文件,需要的朋友可以參考下2022-05-05
java對象類型轉(zhuǎn)換和多態(tài)性(實例講解)
下面小編就為大家?guī)硪黄猨ava對象類型轉(zhuǎn)換和多態(tài)性(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
Spring使用event-stream進(jìn)行數(shù)據(jù)推送
這篇文章主要介紹了Spring使用event-stream進(jìn)行數(shù)據(jù)推送,前端使用EventSource方式向后臺發(fā)送請求,后端接收到之后使用event-stream方式流式返回,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-03-03

