大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中提供的,当然还有更好、更专业的实现方式。对于终结符,建议采用享元模式来共享它们的拷贝,因为它们要多次重复出现。但是考虑到享元模式的使用局限性,建议还是当你的系统中终结符重复的足够多的时候再考虑享元模式。”