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

具體代碼實(shí)現(xiàn):
public abstract class Expression {
// map中攜帶了表達(dá)式中的變量名(key) 和 對(duì)應(yīng)的值(value)
public abstract int interpreter(Map<String, Integer> var);
}
public class VarExpression extends Expression {
// 表達(dá)式中對(duì)應(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 {
// +或-符號(hào) 左右兩邊的表達(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;
}
}
// 最后會(huì)獲得被Expression包裝起來的一個(gè)表達(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
*/
或許看代碼會(huì)有點(diǎn)云里霧里,希望大家能手動(dòng)敲一遍,或許會(huì)對(duì)整個(gè)過程有更進(jìn)一步的理解,在編碼的同時(shí)不斷思考,提升自我。
很容易發(fā)現(xiàn)解釋器模式是屬于行為性模式的一種,這種模式更關(guān)注對(duì)象之間的通信。
解釋器模式優(yōu)點(diǎn),結(jié)構(gòu)清晰,可拓展性好。但也有缺點(diǎn),一般用在比較底層場景,平常敲代碼可使用的場景比較少,并且解釋器模式采用的是遞歸的方式,當(dāng)語言比較長,性能不高;同時(shí)如果文法比較復(fù)雜,也需要更多的相應(yīng)解釋類。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- Java設(shè)計(jì)模式之解釋器模式
- 深入理解Java設(shè)計(jì)模式之解釋器模式
- Java設(shè)計(jì)模式之java解釋器模式詳解
- Java基于解釋器模式實(shí)現(xiàn)定義一種簡單的語言功能示例
- Java設(shè)計(jì)模式之解釋器模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java設(shè)計(jì)模式編程之解釋器模式的簡單講解
- 解析Java的設(shè)計(jì)模式編程之解釋器模式的運(yùn)用
- JAVA設(shè)計(jì)模式之解釋器模式詳解
- Java實(shí)現(xiàn)自定義語言和表達(dá)式解析的解釋器模式
相關(guān)文章
Intellij Idea部署OpenCV 4.0.0環(huán)境
這篇文章主要為大家詳細(xì)介紹了Intellij Idea部署OpenCV 4.0.0環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Java的四種常見線程池及Scheduled定時(shí)線程池實(shí)現(xiàn)詳解
這篇文章主要介紹了Java的四種常見線程池及Scheduled定時(shí)線程池實(shí)現(xiàn)詳解,在Java中,我們可以通過Executors類來創(chuàng)建ScheduledThreadPool,Executors類提供了幾個(gè)靜態(tài)方法來創(chuàng)建不同類型的線程池,包括ScheduledThreadPool,需要的朋友可以參考下2023-09-09
springboot使用log4j2異步日志提升性能的實(shí)現(xiàn)方式
這篇文章主要介紹了springboot使用log4j2異步日志提升性能,異步日志實(shí)現(xiàn)方式:將日志存入一個(gè)單獨(dú)的隊(duì)列中,有一個(gè)單獨(dú)的線程從隊(duì)列中獲取日志并寫入磁盤文件,需要的朋友可以參考下2022-05-05
java對(duì)象類型轉(zhuǎn)換和多態(tài)性(實(shí)例講解)
下面小編就為大家?guī)硪黄猨ava對(duì)象類型轉(zhuǎn)換和多態(tài)性(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
Spring使用event-stream進(jìn)行數(shù)據(jù)推送
這篇文章主要介紹了Spring使用event-stream進(jìn)行數(shù)據(jù)推送,前端使用EventSource方式向后臺(tái)發(fā)送請求,后端接收到之后使用event-stream方式流式返回,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-03-03
Spring實(shí)戰(zhàn)之緩存使用key操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之緩存使用key操作,結(jié)合實(shí)例形式分析了Spring緩存使用key具體配置、屬性、領(lǐng)域模型等相關(guān)操作技巧,需要的朋友可以參考下2020-01-01

