java23種設計模式-直譯器模式
阿新 • • 發佈:2018-12-12
定義
給定一個語言,定義它的文法表示,並定義一個直譯器,這個直譯器使用該標識來解釋語言中的句子
UML
角色
-
抽象表示式(Expression):宣告一個所有的具體表達式角色都需要實現的抽象介面。該介面提供一個interpret()方法。
-
終結符表示式(Terminal Expression) :實現了抽象表示式介面,有一個interpret()方法;文法中的每一個終結符都有一個具體終結表示式與之相對應。比如有一個簡單的公式c=a+b,在裡面a和b就是終結符,對應的解析a和b的直譯器就是終結符表示式。
-
非終結符表示式(Nonterminal Expression):文法中的每一條規則都需要一個具體的非終結符表示式,非終結符表示式一般是文法中的運算子或者其他關鍵字,比如公式c=a+b中,“+"就是非終結符,解析“+”的直譯器就是一個非終結符表示式。
-
環境(Context)角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如c=a+b,我們給a賦值2,給b賦值3。這些資訊需要存放到環境角色中,很多情況下我們使用Map來充當環境角色。
示例
/**
* desc : 抽象表示式
* Created by tiantian on 2018/9/29
*/
public abstract class Expression {
public abstract int interpret(Map<String, Object> map);
}
/** * desc : 變量表達式(角色為:終結符表示式,解析各種變數) * Created by tiantian on 2018/9/29 */ public class VarExpression extends Expression { private String key; public VarExpression(String key) { this.key = key; } public int interpret(Map<String, Object> map) { return (int) map.get(key); } }
/** * desc : 抽象符號表達式 * Created by tiantian on 2018/9/29 */ public abstract class SymbolExpression extends Expression { protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right; } }
/**
* desc : 加法表示式(角色為:非終結符表示式)
* Created by tiantian on 2018/9/29
*/
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
public int interpret(Map<String, Object> map) {
return super.left.interpret(map) + super.right.interpret(map);
}
}
/**
* desc : 減法表示式(角色為:非終結符表示式)
* Created by tiantian on 2018/9/29
*/
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
public int interpret(Map<String, Object> map) {
return super.left.interpret(map) - super.right.interpret(map);
}
}
/**
* desc : 加減法計算器(使用各種直譯器做加減法運算)
* Created by tiantian on 2018/9/30
*/
public class Calculator {
private Expression expression;
public Calculator(String exp) {
char[] charArray = exp.toCharArray();
Stack<Expression> stack = new Stack();
Expression left = null;
Expression right = null;
for (int i = 0; i < charArray.length; i++) {
switch (charArray[i]) {
case '+' : {
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new AddExpression(left, right));
break;
}
case '-' : {
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new SubExpression(left, right));
break;
}
default : {
stack.push(new VarExpression(String.valueOf(charArray[i])));
}
}
}
this.expression = stack.pop();
}
public void doCompute(Map<String,Object> param) {
int res = expression.interpret(param);
System.out.println("Calculete result is : " + res);
}
public static void main(String[] args) {
Calculator calculator = new Calculator("a-b");
Map<String,Object> param = new HashMap<>();
param.put("a", 2);
param.put("b",3);
calculator.doCompute(param);
}
}
總結
直譯器模式的使用場景不是很多。java中比較好的實現有expression4J。擴充套件性好,易於實現簡單的文法,但是文法複雜時程式碼不好維護。