Class AbstractInOrderTraversalVisitor<T>
- Type Parameters:
T- The type of value wrapped in theVisitableobject to be visited by this visitor. For example, if the visitable class isImmutableTreeNode, then the type of value is the return type of itsImmutableTreeNode.getValue()method
- All Implemented Interfaces:
Visitor<T>
Visitor that performs a non-recursive (iterative) in-order traversal of a binary tree.
Subclasses must implement the processNode(TreeNode) method to define what action to take on each node. This
class uses the Template Method pattern, where the traversal algorithm is the template and the node processing is the
customizable step.
Compared with TreeTraverser.traverseInOrder(TreeNode, Visitor), this visitor is assumed to be visiting the
entire tree and uses a very common and practical adaptation where the traversal logic is bundled inside the
visitor. The client just needs to kick it off by calling the Visitable.accept(Visitor) on the root node. The
reason for this common adaptation is for convenience. It simplifies the client code and encapsulates the traversal
algorithm withi the operation that depends on it.
AbstractInOrderTraversalVisitor and TreeTraverser.traverseInOrder(TreeNode, Visitor) reflect the
classic architectural trade-off between convenience and flexibility where the former is favored by
AbstractInOrderTraversalVisitor. Their core difference lies in the separation of responsibilities. The
TreeTraverser.traverseInOrder(TreeNode, Visitor) separates the how (the traversal algorithm) from the
what (the operation performed on a node). The AbstractInOrderTraversalVisitor model combines them.
Using AbstractInOrderTraversalVisitor is simpler for a single, specific task. The user only needs to
instantiate one object and make one call: root.accept(new PrintingVisitor()). It's a winner for simplicity.
In terms of flexibility and reusability, however, this model is rigid. If we want to perform the exact same printing
operation but in a pre-order traversal, we would need to create a whole new PreOrderPrintingVisitor class.
This would require duplicate the printing logic, violating the "Don't Repeat Yourself" (DRY) principle. The traversal
algorithm and the node operation are permanently coupled.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected abstract voidprocessNode(TreeNode<T> node) An abstract method that defines the "visit" operation to be performed on each node during the traversal.voidvisit(ImmutableTreeNode<T> node) Visits anImmutableTreeNode.voidvisit(MutableTreeNode<T> node) Visits aMutableTreeNode.
-
Constructor Details
-
AbstractInOrderTraversalVisitor
public AbstractInOrderTraversalVisitor()
-
-
Method Details
-
processNode
An abstract method that defines the "visit" operation to be performed on each node during the traversal.This is the customizable step in the template method. Although this abstract method introduces a layer of flexibility, it does not achieve the same level of architectural decoupling and reusability as the
TreeTraverser.traverseInOrder(TreeNode, Visitor)model. The key difference lies in what is being coupled:We are coupling the action, i.e. this method, to a specific traversal algorithm (in-order). If we, for example, create a
SummingVisitorthat extendsAbstractInOrderTraversalVisitor, its summing logic is now permanently tied to an in-order traversal. If we later need to sum the nodes using a pre-order traversal, we would have to create an entirely new class that extendsAbstractPreOrderTraversalVisitorabstract class and a newPreOrderSummingVisitorthat duplicates the summing logic. The action is not reusable across different traversal strategies. In the end, having 2 visitors (PrintingVisitor,SummingVisitor) with pre-order, in-order, and post-order capabilities would require client to maintain 2 x 3 = 6 classes of source code.- Parameters:
node- The node to process
-
visit
Description copied from interface:VisitorVisits anImmutableTreeNode. -
visit
Description copied from interface:VisitorVisits aMutableTreeNode.
-