next up previous
Next: References Up: Why Visitors? Previous: Second Attempt: Dedicated Methods.

Third Attempt: The Visitor Pattern.

The Visitor pattern lets us define a new operation on an object structure without changing the classes of the objects on which it operates. Rather than writing dedicated methods for each programming task and afterwards recompiling, the idea is to (1) insert a so-called accept method in each class, and (2) write the action code in so-called visitors.

For our running example, the basic classes and the visitor class look like this:

interface List {
  void accept(Visitor v);
}

class Nil implements List {
  public void accept(Visitor v) {
    v.visitNil(this);
  }
}

class Cons implements List {
  int head;
  List tail;
  public void accept(Visitor v) {
    v.visitCons(this);
  }
}

interface Visitor {
  void visitNil(Nil x);
  void visitCons(Cons x);
}

class SumVisitor implements Visitor {
  int sum = 0;
  public void visitNil(Nil x) {}
  public void visitCons(Cons x) {
    sum = sum + x.head;
    x.tail.accept(this);
  }
}

Each accept method takes a visitor as argument. The interface Visitor has a header for each of the basic classes. We can now compute and print the sum of all components of a given List-object l by writing

SumVisitor sv = new SumVisitor();
l.accept(sv);
System.out.println(sv.sum);

The advantage is that one can write code that manipulates objects of existing classes without recompiling those classes. The price is that all objects must have an accept method.

In summary, the Visitor pattern combines the advantages of the two other approaches. In slogan-form:

  Frequent Frequent
  type casts? recompilation?
Instanceof and type casts Yes No
Dedicated methods No Yes
The Visitor pattern No No

next up previous
Next: References Up: Why Visitors? Previous: Second Attempt: Dedicated Methods.
Jens Palsberg