描述:對一個表達式進行解釋時,將表達式分爲終結符、非終結符、運算環境,這樣區分能夠把表達式的各個部分獨立出來擴展。java
名稱解釋:ide
場景:寫個解釋器,解釋a+b=3,其中a=1,b=2,c=0,另外擴展一個相反數運算使-a=-1。this
實現:code
抽象一個表達式,負責解釋終結符或者非終結符,其定義一個解釋方法,計算表達式的值,同時覆蓋equals和hashCode方法,方便判斷兩個表達式是否相同orm
abstract class Expression { String name; Expression(String name) { this.name = name; } abstract int interpret(Context ctx); @Override public boolean equals(Object obj) { if(null == obj) { return false; } if(obj instanceof String && name.equals(obj)) { return true; } return false; } @Override public int hashCode() { return name.hashCode(); } }
定義一個終結符表達式,也就是負責計算變量的值get
class Variable extends Expression { Variable(String name) { super(name); } @Override int interpret(Context ctx) { return ctx.lookup(this); } }
定一個非終結符表達式,其名爲加法,負責計算兩個終結符的值hash
class AddExpression extends Expression { Expression var1; Expression var2; AddExpression(Expression var1, String name, Expression var2) { super(name); this.var1 = var1; this.var2 = var2; } @Override int interpret(Context ctx) { return var1.interpret(ctx) + var2.interpret(ctx); } }
若是想擴展一種運算,能夠直接定義一個非終結符表達式,好比定義一個求相反數的運算it
//一個數的相反數 class OppositeExpression extends Expression { Expression var; OppositeExpression(String name, Expression var) { super(name); this.var = var; } @Override int interpret(Context ctx) { return -var.interpret(ctx); } }
定義一個運算環境,用於給變量賦值io
class Context { Map<Expression, Integer> map = new HashMap<Expression, Integer>(); void assign(Expression var, int value) { map.put(var, value); } int lookup(Expression var) { Object obj = map.get(var); if(null == obj) { // 若是變量未初始化,默認是0 return 0; } return (Integer) obj; } }
客戶端調用:form
public static void main(String[] args) { Context ctx = new Context(); Variable a = new Variable("a"); Variable b = new Variable("b"); Variable c = new Variable("c"); // 不初始化,默認爲0 ctx.assign(a, 1); ctx.assign(b, 2); System.out.println("a = " + a.interpret(ctx)); System.out.println("b = " + b.interpret(ctx)); System.out.println("c = " + c.interpret(ctx)); // 相反數運算 OppositeExpression opposite = new OppositeExpression("-", a); int rs = opposite.interpret(ctx); String exp = String.format("%s%s = %d", opposite.name, a.name, rs); System.out.println(exp); // 加運算 AddExpression add = new AddExpression(a, "+", b); rs = add.interpret(ctx); exp = String.format("%s %s %s = %d", a.name, add.name, b.name, rs); System.out.println(exp); }
結果:
a = 1 b = 2 c = 0 -a = -1 a + b = 3