Suppose I have a composite hierarchy to represent regular expresions, like this:
public abstract class Expression {
public abstract void accept(Visitor visitor);
}
public class Identifier extends Expression {
public final String token;
public Identifier(String token) {
this.token = token;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String getToken() {
return token;
}
}
public class Sequence extends Expression {
private final List<Expression> subExprs;
public Sequence(List<Expression> subExprs) {
this.subExprs = new ArrayList<Expression>(subExprs);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public List<Expression> getSubExprs() {
return subExprs;
}
}
...
public abstract class Visitor {
public abstract void visit(Identifier identifier);
public abstract void visit(Sequence sequence);
}
The question is, how do I implement operations that need to crawl the tree and calculate the results recursively, such as:
- serialize a regexp to string,
- evaluate a regexp to a set of sequences,
- ...
Suppose for example the following Visitor implementation:
public class Serialize extends Visitor {
public void visit(Sequence sequence) {
for (Expression subExpr : sequence.getSubExprs()) {
// here, I don't have any means to access the sub-results
subExpr.accept(visitor);
}
}
...
}
To calculate the result at any given level of the tree, I need to know the sub-results at the levels below. Ideally I would need the accept method to return the calculated result. This does not seem to be possible, though, as individual operations might return results of different type.
The only solution that comes to my mind is to cache the sub-results manually in a map on the visitor class. This seems very cumbersome, though.
Is Visitor a suitable pattern in this case? What would be a suitable implementation?
Aucun commentaire:
Enregistrer un commentaire