網(wǎng)站建設(shè)和網(wǎng)絡(luò)推廣外包服務(wù)商seo超級外鏈發(fā)布
解釋器模式是一種行為設(shè)計(jì)模式,可以解釋語言的語法或表達(dá)式。給定一個語言,定義它的文法的一種表示,然后定義一個解釋器,使用該文法來解釋語言中的句子。解釋器模式提供了評估語言的語法或表達(dá)式的方式。
Interpreter is a behavior design pattern. It can interpret the syntax or expressions of a language.
Given a language, define a representation of its grammar, and then define an interpreter
that uses the grammar to interpret sentences by the language.
結(jié)構(gòu)設(shè)計(jì)
解釋器模式包含如下角色:
Context,上下文,包含解釋器之外的一些全局信息。
AbstractExpression,抽象表達(dá)式,聲明一個抽象的解釋操作,這個接口為抽象語法樹中所有的節(jié)點(diǎn)所共享。
TerminalExression,終結(jié)符表達(dá)式,實(shí)現(xiàn)與文法中的終結(jié)符相關(guān)聯(lián)的解釋操作。
NonterminalExpression,非終結(jié)符表達(dá)式,實(shí)現(xiàn)與文法中的非終結(jié)符相關(guān)聯(lián)的解釋操作,對文法中每一條規(guī)則R1、R2、…、Rn 都需要一個具體的非終結(jié)符表達(dá)式類。
Client,客戶端,構(gòu)建一個句子,它是TerminalExression和NonterminalExpression的實(shí)例的一個抽象語法樹,然后初始化Context,并調(diào)用解釋操作。
解釋器模式類圖表示如下:
偽代碼實(shí)現(xiàn)
接下來將使用代碼介紹下解釋器模式的實(shí)現(xiàn)。由于無法使用抽象的用例表示出解釋器模式,所以這里會基于特定的場景給出代碼示例。這里以常見的四則運(yùn)算(由于除法需要特殊處理,這里暫不提供)的解析為例,
介紹下解釋器模式的實(shí)現(xiàn)。
// 1、抽象表達(dá)式,聲明一個抽象的解釋操作接口
public interface Expression {int interpret();
}//2、終結(jié)符表達(dá)式,實(shí)現(xiàn)與文法中的終結(jié)符相關(guān)聯(lián)的解釋操作,這里是數(shù)字
public class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}public NumberExpression(String number) {this.number = Integer.parseInt(number);}@Overridepublic int interpret() {return this.number;}
}// 3、非終結(jié)符表達(dá)式,實(shí)現(xiàn)與文法中的非終結(jié)符相關(guān)聯(lián)的解釋操作,這里是運(yùn)算符
public class AdditionExpression implements Expression {private Expression firstExpression, secondExpression;public AdditionExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.addExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "+";}
}
public class SubtractionExpression implements Expression {private Expression firstExpression, secondExpression;public SubtractionExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.subtractExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "-";}
}
public class MultiplicationExpression implements Expression {private Expression firstExpression, secondExpression;public MultiplicationExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.multiplyExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "*";}
}// 4、表達(dá)式分析器,將輸入解析成表達(dá)式并執(zhí)行相關(guān)的計(jì)算
public class ExpressionParser {private static final String ADD = "+";private static final String SUBTRACT = "-";private static final String MULTIPLY = "*";private static final String SPLITTER = " ";private LinkedList<Expression> stack = new LinkedList();public int parse(String str) {String[] tokenList = str.split(SPLITTER);for (String symbol : tokenList) {if (!isOperator(symbol)) {Expression numberExpression = new NumberExpression(symbol);stack.push(numberExpression);} else {Expression firstExpression = stack.pop();Expression secondExpression = stack.pop();Expression operator = getExpressionObject(firstExpression, secondExpression, symbol);if (operator == null) {throw new RuntimeException("unknown symbol: " + symbol);}int result = operator.interpret();NumberExpression resultExpression = new NumberExpression(result);stack.push(resultExpression);}}return stack.pop().interpret();}private boolean isOperator(String symbol) {return symbol.equals(ADD) || symbol.equals(SUBTRACT) || symbol.equals(MULTIPLY);}private Expression getExpressionObject(Expression firstExpression, Expression secondExpression, String symbol) {switch (symbol) {case ADD:return new AdditionExpression(firstExpression, secondExpression);case SUBTRACT:return new SubtractionExpression(firstExpression, secondExpression);case MULTIPLY:return new MultiplicationExpression(firstExpression, secondExpression);default:return null;}}
}// 5、客戶端
public class InterpreterClient {public void test() {// (1) 定義輸入String input = "2 1 5 + *";System.out.println("input is: " + input);// (2) 創(chuàng)建表達(dá)式分析器實(shí)例ExpressionParser expressionParser = new ExpressionParser();// (3) 執(zhí)行分析操作int result = expressionParser.parse(input);System.out.println("result: " + result);}
}
適用場景
在以下情況下可以考慮使用解釋器模式:
(1)如果需要解釋執(zhí)行的語言中的句子,可以表示為一個抽象語法樹,可以考慮使用解釋器模式。如SQL 解析、符號處理引擎、正則表達(dá)式等。
(2) 對于重復(fù)出現(xiàn)的問題,如果可以使用簡單的語言來表達(dá),可以考慮使用解釋器模式。
(3) 一個簡單語法需要解釋的場景,可以考慮使用解釋器模式。對于簡單語法,由于其文法規(guī)則較簡單,使用解釋器模式要優(yōu)于語法分析程序。
優(yōu)缺點(diǎn)
解釋器模式有以下優(yōu)點(diǎn):
(1) 可擴(kuò)展性好。因?yàn)樵撃J绞褂妙悂肀硎疚姆ㄒ?guī)則,可以使用繼承來改變或擴(kuò)展該文法。
(2) 易于實(shí)現(xiàn)簡單的文法。定義抽象語法樹各個節(jié)點(diǎn)的類的實(shí)現(xiàn)大體相似。
但是該模式也存在以下缺點(diǎn):
(1) 可利用場景比較少。
(2) 對于復(fù)雜的文法比較難維護(hù)。包含許多規(guī)則的文法可能難以管理和維護(hù)。
(3) 會引起類膨脹。隨著文法規(guī)則的復(fù)雜化,類的規(guī)模也會隨之膨脹。
(4) 使用了大量的循環(huán)和遞歸,需要考慮效率問題。
參考
《設(shè)計(jì)模式 可復(fù)用面向?qū)ο筌浖幕A(chǔ)》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英軍, 馬曉星等譯
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/mediator.html 解釋器模式
https://refactoringguru.cn/design-patterns/mediator 解釋器模式
https://www.runoob.com/design-pattern/mediator-pattern.html 解釋器模式
https://www.cnblogs.com/adamjwh/p/10959987.html 簡說設(shè)計(jì)模式——解釋器模式
https://springframework.guru/gang-of-four-design-patterns/interpreter-pattern/ Interpreter Pattern