上面的示例中,每次使用时,都需要借助于new 按照抽象语法树的形式创建一堆对象
比如计算1+2与3+4
是不是可以转换为公式的形式呢?
也就是仅仅定义一次表达式,不管是1+2 还是3+4还是6+8 都可以计算?
所以我们考虑增加“变量”这一终结符表达式节点
增加变量类Variable 终结符节点
内部包含名称和值,提供值变更的方法
package interpret;
public class Variable extends AbstractExpression{
private String name;
private Integer value;
Variable(String name,Integer value){
this.name = name;
this.value = value;
}
public void setValue(Integer value) {
this.value = value;
}
@Override
public int interpret() {
return value;
}
}
package interpret;
public class Client {
public static void main(String[] args) {
//定义变量X和Y,初始值都为0
Variable variableX = new Variable("x", 0);
Variable variableY = new Variable("y", 0);
//计算公式为: X+Y+X-1
AbstractExpression expression2 = new Minus(new Plus(new Plus(variableX, variableY), variableX),
new Value(1));
variableX.setValue(1);
variableY.setValue(3);
System.out.println(expression2.interpret());
variableX.setValue(5);
variableY.setValue(6);
System.out.println(expression2.interpret());
}
}
有了变量类 Variable,就可以借助于变量进行公式的计算
而且,很显然,
公式只需要设置一次,而且可以动态设置
通过改变变量的值就可以达到套用公式的目的
一般的做法并不是直接将值设置在变量类里面,变量只有一个名字,将节点所有的值设置到Context类中
Context的作用可以通过示例代码感受下
代码示例
完整示例如下
AbstractExpression抽象表达式角色 接受参数Context,如有需要可以从全局空间中获取数据
package interpret.refactor;
public abstract class AbstractExpression {
public abstract int interpret(Context ctx);
}
数值类Value 终结符表达式节点
内部还有int value
他不需要从全局空间获取数据,所以interpret方法中的Context用不到
增加了toString方法,用于呈现 数值类的toString方法直接回显数值的值
package interpret.refactor;
public class Value extends AbstractExpression {
private int value;
Value(int value) {
this.value = value;
}
@Override
public int interpret(Context ctx) {
return value;
}
@Override
public String toString() {
return new Integer(value).toString();
}
}
变量类Variable 终结符表达式
变量类拥有名字,使用内部的String name
变量类的真值保存在Context中,Context是借助于hashMap存储的
Context定义的类型为Map<Variable, Integer>
所以,我们重写了equals以及hashCode方法
Variable的值存储在Context这一全局环境中,值也是从中获取
package interpret.refactor;
public class Variable extends AbstractExpression {
private String name;
Variable(String name) {
this.name = name;
}
@Override
public int interpret(Context ctx) {
return ctx.getValue(this);
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof Variable) {
return this.name.equals(
((Variable) obj).name);
}
return false;
}
@Override
public int hashCode() {
return this.toString().hashCode();
}
@Override
public String toString() {
return name;
}
}
加法跟原来差不多,interpret接受参数Context,如有需要从Context中读取数据
package interpret.refactor;
public class Plus extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
Plus(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context ctx) {
return left.interpret(ctx) + right.interpret(ctx);
}
@Override
public String toString() {
return "(" + left.toString() + " + " + right.toString() + ")&q