Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

@Pattern(name="Visitor", scope=Object, purpose=Behavioural, participants={"Visitor","ConcreteVisitor","Element","ConcreteElement","ObjectStructure"})

Package dk.rode.thesis.visitor

Implementations and examples of the Visitor design pattern [Gamma95, p.331].

See:
          Description

Interface Summary
SequenceTypeScanner A sequence type scanner performs the actual traversal of the sequence structure to be visited by a type visitor, invoking the TypeVisitableSequence.accept(SequenceTypeVisitor, Object) visitation method on each found type visitable sequence.
SequenceTypeVisitor<P> A sequence type visitor visits a sequence based on its actual type, for example ReversibleSequence or MemorizableSequence.
SequenceValueScanner A sequence value scanner performs the actual traversal of the sequence structure to be visited by a value visitor, invoking the ValueVisitableSequence.accept(SequenceValueVisitor, Object) visitation method on each found value visitable sequence.
SequenceValueVisitor<P> A sequence value visitor visits a sequence based on the type of values it deliver, for example Integer or Date.
SequenceVisitor<P> A sequence visitor is the super type for all visitors that can visit a sequence type.
TypeVisitableSequence<E> A type visitable sequence allows visitation by type visitors.
ValueVisitableSequence<E> A value visitable sequence allows visitation by value visitors.
 

Class Summary
AbstractVisitableSequence<E> Any sequence decorated by an abstract visitable sequence implementation is value and type visitable.
CountingVisitor A counting visitor counts the different types of value visitable sequences encountered during traversal, and is thus independent of any given scanner implementation.
DateValuedVisitableSequence A date valued visitable sequence allows any sequence delivering Date values to become value visitable using the SequenceValueVisitor.visitDateValued(Sequence, Object) visitation method and is type visitable for any known sub-interface of Sequence that is implemented by the sequence.
IntegerValuedVisitableSequence An integer valued visitable sequence allows any sequence delivering Integer values to become value visitable using the SequenceValueVisitor.visitIntegerValued(Sequence, Object) visitation method and is type visitable for any known sub-interface of Sequence that is implemented by the sequence.
LoggingVisitor A logging visitor logs each visited sequence to a log supplied at execution time using a given sequence policy supplied at construction time.
Main Visitor tests.
ReflectiveVisitableSequence<E> A reflective visitable sequence decorates a sequence to become value and type visitable.
SimpleScanner A simple scanner can traverse both type and value visitable sequences based on a traversal strategy that can be supplied at construction time, or changed runtime using the SimpleScanner.setCompositeStrategy(CompositeStrategy) method.
StringValuedVisitableSequence<E extends CharSequence> A string valued visitable sequence allows any sequence delivering any CharSequence type to become value visitable using the SequenceValueVisitor.visitStringValued(Sequence, Object) visitation method and is type visitable for any known sub-interface of Sequence that is implemented by the sequence.
TypeVisitor A type visitor collects visited sequences based on acceptance of specific sequence types.
VisitableCompositeSequence An visitable composite sequence is value and type visitable, storing sequences regardless of the type of value they deliver.
VisitableLongSequence A visitable long sequence is a LongSequence that is value visitable using the SequenceValueVisitor.visitLongValued(Sequence, Object) visitation method and is type visitable as well.
VisitableRandomSequence A visitable random sequence is a RandomSequence that is value visitable only using the SequenceValueVisitor.visitIntegerValued(Sequence, Object) visitation method.
VisitableReversiblePrimeSequence A visitable reversible prime sequence is a ReversiblePrimeSequence that is value visitable using the SequenceValueVisitor.visitIntegerValued(Sequence, Object) visitation method and is type visitable as well.
 

Package dk.rode.thesis.visitor Description

Implementations and examples of the Visitor design pattern [Gamma95, p.331].

Intent:

Here, the Visitor participant is represented by not one, but two separate visitor implementations, namely the SequenceTypeVisitor and SequenceValueVisitor classes. The first is a type visitor to visit a given Sequence based on its type, e.g. ReversibleSequence, while the latter is a value visitor that visits based on the type of sequence values, e.g. Integer, Date, CharSequence, etc. The use of two different visitors help illustrate visitor usage more clearly than just using a single type.

The Element participant is represented by the TypeVisitableSequence and ValueVisitableSequence interfaces, respectively for visitation by SequenceTypeVisitor and SequenceValueVisitor implementations. A given Sequence may naturally implement both interfaces. The ConcreteElement participant is represented by any sequence that implement either or both of these interfaces.

The ConcreteVisitor participant is represented by any SequenceTypeVisitor and SequenceValueVisitor implementation. In this package, three visitors are implemented, namely TypeVisitor (type visitor), CountingVisitor (value visitor), and LoggingVisitor (type and value visitor).

A tree-like element (sequence) structure is achieved by using the CompositeSequence or VisitableCompositeSequence types, combined with non-composite (visitable) sequences. To traverse such a Sequence structure for a given type or value visitor, SequenceTypeScanner and SequenceValueScanner implementations should be used, respectively. They represent the ObjectStructure participant. A concrete implementation has been made than can traverse a sequence structure for both type and value visitors in form of SimpleScanner.

This package defines three concrete visitable sequences (excluding the composite visitable sequence): VisitableRandomSequence, VisitableLongSequence, and VisitableReversiblePrimeSequence. The first is only visitable by value visitors, while last two can be visited by both type and value visitors.

A visitable sequence rarely adds new state to the sequence it inherits. In fact, the primary reason for inheritance is to implement the TypeVisitableSequence and/or ValueVisitableSequence interfaces because of Java's fixed class structure. To avoid overly use of inheritance, several wrappers (decorators) have been developed in this package that will wrap a given sequence and make it visitable. For example, the StringValuedVisitableSequence class allows any Sequence<? extends CharSequence> type to become both type and value visitable. Such wrappers all extend AbstractVisitableSequence.

Finally, a reflective wrapper in form of the ReflectiveVisitableSequence class has been created that allows any sequence to become both value and type visitable based on reflective TypeLiteral functionality.

UML Class Diagram:

Implementation notes:
Though two different types of visitors are used, they operate on the same class hierarchy, i.e. Sequence, but with different focus, i.e. sequence type vs. sequence values.

SequenceTypeVisitor implementations are not completely accurate when decorated, adapted, and/or proxied sequences are used, because the instanceof test will fail in such cases. However, this is a general problem related to the use of decorators, adapters, and proxies, not specifically to visitors.

While the ReflectiveVisitableSequence class can make any sequence visitable, it may not be able to infer the correct sequence value type in case the sequence is generic. The sequence in question may also deliver a value not supported by the SequenceValueVisitor interface. In such cases, the default visitation method is used.

In the implementation here, visiting a composite sequence is just like visiting a non-composite sequence, because the SequenceTypeScanner and SequenceValueScanner implementations, respectively, will handle the sequence traversal explicitly.

Author:
Gunni Rode / rode.dk

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.