I have been trying to design an expression evaluator using visitor framework. Before going into my current design here are few problems that I am facing.
- Current design works well with arithmetic operators but when it comes to logical operators for eg
5 > 6
will output tofalse
it doesn't work. AsVisitor
is a generic interface so if I sayVisitor<Boolean>
the return value will becomeboolean
but participating values areinteger
hence I am not able to have integer as parameter. - The design requires a class for every operator can it be minimized?
- Please share your inputs on design. Does it look good or any modification needed.
Following are participating classes.
Here is visitor interface
public interface Visitor<T> {
T visit(Expression expression);
T visit(BinaryExpression binaryExpression);
T visit(ConstantExpression expression);
}
visitor implementation
public class ExpressionVisitor<T> implements Visitor<T> {
@Override
public T visit(Expression expression) {
return expression.accept(this);
}
@Override
public T visit(BinaryExpression arithmeticExpression) {
Operator op = arithmeticExpression.getOperator();
T left = visit(arithmeticExpression.getLeft());
T right = visit(arithmeticExpression.getRight());
return op.apply(left, right);
}
@Override
public T visit(ConstantExpression expression) {
return (T) expression.getValue();
}
}
A class which represents expression
public abstract class Expression {
public abstract <T> T accept(Visitor<T> visitor);
}
Class for binary expression
public class BinaryExpression extends Expression {
private Operator operator;
private Expression left;
private Expression right;
//constructor and getters
@Override public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
A class that represents Constant value
public class ConstantExpression extends Expression {
private Object value;
//constructor and getter
@Override public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
Operator clas
public abstract class Operator {
public <T> T apply(T left, T right) {
try {
Method method = this.getClass().getMethod("do" + left.getClass().getSimpleName() + this.getClass().getSimpleName(), left.getClass(), right.getClass());
method.setAccessible(true);
return (T) method.invoke(this, left, right);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException("Failed");
}
}
}
And Addition operator
public class Addition extends Operator {
public Integer doIntegerAddition(Integer left, Integer right) {
return left + right;
}
public Double doDoubleAddition(Double left, Double right) {
return left + right;
}
public String doStringAddition(String left, String right) {
return left + right;
}
}
Aucun commentaire:
Enregistrer un commentaire