大B:“來舉一個加減乘除的例子吧,實現思路來自於《java與模式》中的例子。每個角色的功能按照上面提到的規範來實現。”
//上下文(環境)角色,使觓shMap來儲存變數對應的數值
classContext
{
privateMapvalueMap=newHashMap();
publicvoidaddValue(Variablex,inty)
{
Integeryi=newInteger(y);
valueMap.put(x,yi);
}
publicintLookupValue(Variablex)
{
inti=((Integer)valueMap.get(x)).intValue();
returni;
}
}
//抽象表示式角色,也可以用介面來實現
abstractclassEXPression
{
publicabstractintinterpret(Contextcon);
}
//終結符表示式角色
classConstantextendsExpression
{
privateinti;
publicConstant(inti)
{
this.i=i;
}
publicintinterpret(Contextcon)
{
returni;
}
}
classVariableextendsExpression
{
publicintinterpret(Contextcon)
{
//this為呼叫interpret方法的Variable物件
returncon.LookupValue(this);
}
}
//非終結符表示式角色
classAddextendsExpression
{
privateExpressionleft,right;
publicAdd(Expressionleft,Expressionright)
{
this.left=left;
this.right=right;
}
publicintinterpret(Contextcon)
{
returnleft.interpret(con)+right.interpret(con);
}
}
classSuBTractextendsExpression
{
privateExpressionleft,right;
publicSubtract(Expressionleft,Expressionright)
{
this.left=left;
this.right=right;
}
publicintinterpret(Contextcon)
{
returnleft.interpret(con)-right.interpret(con);
}
}
classMultiplyextendsExpression
{
privateExpressionleft,right;
publicMultiply(Expressionleft,Expressionright)
{
this.left=left;
this.right=right;
}
publicintinterpret(Contextcon)
{
returnleft.interpret(con)*right.interpret(con);
}
}
classDivisionextendsExpression
{
privateExpressionleft,right;
publicDivision(Expressionleft,Expressionright)
{
this.left=left;
this.right=right;
}
publicintinterpret(Contextcon)
{
try{
returnleft.interpret(con)/right.interpret(con);
}catch(ArithmeticExceptionae)
{
System.out.println(“被除數為0!”);
return-11111;
}
}
}
//測試程式,計算(a*b)/(a-b+2)
publicclassTest
{
privatestaticExpressionex;
privatestaticContextcon;
publicstaticvoidmain(String[]args)
{
con=newContext();
//設定變數、常量
Variablea=newVariable();
Variableb=newVariable();
Constantc=newConstant(2);
//為變數賦值
con.addValue(a,5);
con.addValue(b,7);
//運算,對句子的結構由我們自己來分析,構造
ex=newDivision(newMultiply(a,b),newAdd(newSubtract(a,b),c));
System.out.println(運算結果為:+ex.interpret(con));
}
}
大B:“直譯器模式並沒有說明如何建立一個抽象語法樹,因此它的實現可以多種多樣,在上面我們是直接在Test中提供的,當然還有更好、更專業的實現方式。對於終結符,建議採用享元模式來共享它們的複製,因為它們要多次重複出現。但是考慮到享元模式的使用侷限性,建議還是當你的系統中終結符重複的足夠多的時候再考慮享元模式。”