Skip to content

Instantly share code, notes, and snippets.

@manuelleduc
Created September 5, 2019 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manuelleduc/3734aaa491c8b971ac3d7b3097b2084f to your computer and use it in GitHub Desktop.
Save manuelleduc/3734aaa491c8b971ac3d7b3097b2084f to your computer and use it in GitHub Desktop.
Example Visitor vs Revisitor
package tree;
import tree.model.Leaf;
import tree.model.Node;
import tree.revisitor.RevisitorMax;
import tree.revisitor.RevisitorSum;
import tree.visitor.VisitorMax;
import tree.visitor.VisitorSum;
public class Main {
public static void main(String[] args) {
var tree = new Node(new Node(new Leaf(1), new Leaf(2)), new Leaf(3));
System.out.println(tree.accept(new VisitorSum()));
System.out.println(tree.accept(new VisitorMax()));
System.out.println(new RevisitorSum() {}.$(tree));
System.out.println(new RevisitorMax() {}.$(tree));
}
}
package tree.model;
import tree.visitor.Visitor;
public class Leaf extends Tree {
private final long value;
public Leaf(long value) {
this.value = value;
}
public long getValue() {
return value;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.leaf(this);
}
}
package tree.model;
import tree.visitor.Visitor;
public class Node extends Tree {
private final Tree left;
private final Tree right;
public Node(Tree left, Tree right) {
this.left = left;
this.right = right;
}
public Tree getLeft() {
return left;
}
public Tree getRight() {
return right;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.node(this);
}
}
package tree.model;
import tree.visitor.Visitor;
public abstract class Tree {
public abstract <T> T accept(Visitor<T> visitor);
}
package tree.revisitor;
import tree.model.Leaf;
import tree.model.Node;
import tree.model.Tree;
public interface Revisitor<TT, LT extends TT, NT extends TT> {
LT leaf(Leaf it);
NT node(Node it);
default TT $(Tree it) {
if (it instanceof Leaf) return leaf((Leaf) it);
if (it instanceof Node) return node((Node) it);
return null;
}
default LT $(Leaf it) {
return leaf(it);
}
default NT $(Node it) {
return node(it);
}
}
package tree.revisitor;
import tree.model.Leaf;
import tree.model.Node;
public interface RevisitorMax extends Revisitor<Long, Long, Long> {
@Override
default Long leaf(Leaf it) {
return it.getValue();
}
@Override
default Long node(Node it) {
final var left = $(it.getLeft());
final var right = $(it.getRight());
return left > right ? left : right;
}
}
package tree.revisitor;
import tree.model.Leaf;
import tree.model.Node;
public interface RevisitorSum extends Revisitor<Long, Long, Long> {
@Override
default Long leaf(Leaf it) {
return it.getValue();
}
@Override
default Long node(Node it) {
final var left = $(it.getLeft());
final var right = $(it.getRight());
return left + right;
}
}
package tree.visitor;
import tree.model.Leaf;
import tree.model.Node;
public interface Visitor<T> {
T leaf(Leaf it);
T node(Node it);
}
package tree.visitor;
import tree.model.Leaf;
import tree.model.Node;
public class VisitorMax implements Visitor<Long> {
@Override
public Long leaf(Leaf it) {
return it.getValue();
}
@Override
public Long node(Node it) {
final var left = it.getLeft().accept(this);
final var right = it.getRight().accept(this);
return left > right ? left : right;
}
}
package tree.visitor;
import tree.model.Leaf;
import tree.model.Node;
public class VisitorSum implements Visitor<Long> {
@Override
public Long leaf(Leaf it) {
return it.getValue();
}
@Override
public Long node(Node it) {
final var left = it.getLeft();
final var right = it.getRight();
return left.accept(this) + right.accept(this);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment