解釋器模式屬于行為型模式;指給分析物件定義一個語言,并定義該語言的文法表示,再設計一個決議器來解釋語言中的句子,也就是說,用編譯語言的方式來分析應用中的實體,這種模式實作了文法運算式處理的介面,該介面解釋一個特定的背景關系,
解釋器模式的UML類圖如下所示:

由上圖可知,解釋器模式涉及到抽象運算式(Abstract Expression)角色、終結符運算式(Terminal Expression)角色、非終結符運算式(Nonterminal Expression)角色、環境(Context)角色、客戶端(Client)角色等五種角色:
- 抽象運算式(Abstract Expression)角色:定義解釋器的介面,約定解釋器的解釋操作,主要包含解釋方法 interpret(),
- 終結符運算式(Terminal Expression)角色:是抽象運算式的子類,用來實作文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結運算式與之相對應,
- 非終結符運算式(Nonterminal Expression)角色:也是抽象運算式的子類,用來實作文法中與非終結符相關的操作,文法中的每條規則都對應于一個非終結符運算式,
- 環境(Context)角色:通常包含各個解釋器需要的資料或是公共的功能,一般用來傳遞被所有解釋器共享的資料,后面的解釋器可以從這里獲取這些值,
- 客戶端(Client):主要任務是將需要分析的句子或運算式轉換成使用解釋器物件描述的抽象語法樹,然后呼叫解釋器的解釋方法,當然也可以通過環境角色間接訪問解釋器的解釋方法,
模擬java語言對布爾運算式操作的例子
例子的UML類圖:

抽象運算式角色:
package com.charon.interpreter;
/**
* @author :charon
* @description: 這個抽象類代表終結類和非終結類的抽象化,其中終結類和非終結類的語法如下:
* Expression ::= Expression AND Expression
* | Expression OR Expression
* | NOT Expression
* | Variable (非空白字串)
* | Constant (true | false)
* @date : 2022/4/7 8:32
* @version: 1.0
*/
public abstract class Expression {
/**
* 解釋給定的任何一個運算式
* @param context
* @return
*/
public abstract boolean interpret(Context context) throws IllegalAccessException;
/**
* 檢驗兩個運算式在結構上是否相同
* @param object
* @return
*/
@Override
public abstract boolean equals(Object object);
/**
* 將運算式轉換成字串
* @return
*/
@Override
public abstract String toString();
}
非終結符運算式角色:
package com.charon.interpreter;
/**
* @author :charon
* @description: 邏輯與的操作 ,表示由兩個布爾運算式通過邏輯與操作給出一個新的布爾運算式
* @date : 2022/4/7 10:12
* @version: 1.0
*/
public class And extends Expression{
private Expression left,right;
public And(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(Context context) throws IllegalAccessException {
return left.interpret(context) && right.interpret(context);
}
@Override
public boolean equals(Object object) {
if(object != null && object instanceof And){
return this.left.equals(((And) object).left) && this.right.equals(((And) object).right);
}
return false;
}
@Override
public String toString() {
return "( " + left.toString() + " AND " + right.toString() + ")";
}
}
package com.charon.interpreter;
/**
* @author :charon
* @description: 邏輯或操作
* @date : 2022/4/7 18:03
* @version: 1.0
*/
public class Or extends Expression{
private Expression left,right;
public Or(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(Context context) throws IllegalAccessException {
return left.interpret(context) || right.interpret(context);
}
@Override
public boolean equals(Object object) {
if(object != null && object instanceof Or){
return this.left.equals(((Or) object).left) && this.right.equals(((Or) object).right);
}
return false;
}
@Override
public String toString() {
return "( " + left.toString() + " OR " + right.toString() + ")";
}
}
package com.charon.interpreter;
/**
* @author :charon
* @description: 邏輯非的操作
* @date : 2022/4/7 10:12
* @version: 1.0
*/
public class Not extends Expression{
private Expression expression;
public Not(Expression expression) {
this.expression = expression;
}
@Override
public boolean interpret(Context context) throws IllegalAccessException {
return !expression.interpret(context);
}
@Override
public boolean equals(Object object) {
if(object != null && object instanceof Not){
return this.expression.equals(((Not) object).expression);
}
return false;
}
@Override
public String toString() {
return "( not " + expression.toString() + ")";
}
}
終結符運算式角色:
package com.charon.interpreter;
/**
* @author :charon
* @description: 有名變數
* @date : 2022/4/7 8:43
* @version: 1.0
*/
public class Variable extends Expression{
private String name;
public Variable(String name) {
this.name = name;
}
@Override
public boolean interpret(Context context) throws IllegalAccessException {
return context.lookUp(this);
}
@Override
public boolean equals(Object object) {
if (object != null && object instanceof Variable){
return this.name.equals(((Variable) object).name);
}
return false;
}
@Override
public String toString() {
return name;
}
}
環境類角色:
package com.charon.interpreter;
import java.util.HashMap;
import java.util.Map;
/**
* @author :charon
* @description: 環境類定義
* @date : 2022/4/7 8:38
* @version: 1.0
*/
public class Context {
private Map<Object,Object> map = new HashMap<>();
/**
*
* @param variable
* @param value
*/
public void assign(Variable variable,boolean value){
map.put(variable, value);
}
/**
* 獲取值
* @param variable
* @return
*/
public boolean lookUp(Variable variable) throws IllegalAccessException {
Boolean value = https://www.cnblogs.com/pluto-charon/archive/2022/04/07/(Boolean) map.get(variable);
if(value == null){
throw new IllegalAccessException();
}
return value.booleanValue();
}
}
客戶端角色:
package com.charon.interpreter;
/**
* @author :charon
* @description:
* @date : 2022/4/7 8:31
* @version: 1.0
*/
public class Client {
public static void main(String[] args) throws IllegalAccessException {
Context context = new Context();
Variable x = new Variable("x");
Variable y = new Variable("y");
Constant constant = new Constant(true);
context.assign(x,false);
context.assign(y,true);
Expression expression = new Or(new And(constant, x), new And(y, new Not(x)));
System.out.println("x = " + x.interpret(context));
System.out.println("y = " + y.interpret(context));
System.out.println(expression + " = " + expression.interpret(context));
}
}
列印:
x = false
y = true
( ( true AND x) OR ( y AND ( not x))) = true
解釋器模式的主要優點如下:
- 擴展性好,由于在解釋器模式中使用類來表示語言的文法規則,因此可以通過繼承等機制來改變或擴展文法,
- 容易實作,在語法樹中的每個運算式節點類都是相似的,所以實作其文法較為容易,
解釋器模式的主要缺點如下:
- 執行效率較低,解釋器模式中通常使用大量的回圈和遞回呼叫,當要解釋的句子較復雜時,其運行速度很慢,且代碼的除錯程序也比較麻煩,
- 會引起類膨脹,解釋器模式中的每條規則至少需要定義一個類,當包含的文法規則很多時,類的個數將急劇增加,導致系統難以管理與維護,
- 可應用的場景比較少,在軟體開發中,需要定義語言文法的應用實體非常少,所以這種模式很少被使用到,
模式的應用場景
-
當語言的文法較為簡單,且執行效率不是關鍵問題時,
-
當問題重復出現,且可以用一種簡單的語言來進行表達時,
-
當一個語言需要解釋執行,并且語言中的句子可以表示為一個抽象語法樹的時候,如 XML 檔案解釋,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/457564.html
標籤:其他
