JB Header
Visitor Design Pattern in Java
This article explains Visitor design pattern in java with class diagrams and example code. Introduction Visitor Design Pattern is a behavioral design pattern among the Gang Of Four(GOF)Article on GOF Patterns & their types Design Patterns. Being a behavioral design pattern, the visitor pattern deals with how the classes interact with each other.
What is Visitor Design Pattern Visitor pattern defines operations in a way that they can be performed on the objects arranged in a structure independently of the object structure itself. Independently here implies that these operations are added & applied independently of the object structure on which they operate. Object Structure here refers to how the objects are related to one another such as nodes in a tree, graph etc.
Typical structure of classes in Visitor Design Pattern There are 2 independent class hierarchies in a typical visitor pattern implementation-
  1. Element Hierarchy is for the elements which are to be worked upon.
  2. Visitor hierarchy is for the Visitors which operate on the Element Hierarchy.
  3. Where -
    • Visitor & Element hierarchies are independent of each other in definition and compilation. This allows us to add classes in Visitor Hierarchy to apply operations on classes in the Element Hierarchy as they are traversed.
    • Visitor hierarchy adds a new node for every new operation to be performed on the Element Hierarchy. This new Visitor node has a separate method for each of the nodes in the Element Hierarchy.
Lets look at the class diagram of a Visitor pattern to understand the hierarchies better -

Class Diagram for Visitor Design Pattern
Visitor Design Pattern Class Diagram
Explanation of Visitor Design Pattern Class Diagram
  • There are two distinct hierarchies in the class diagram above.
  • Visitor is the base interface for Visitor Hierarchy. All the ConcreteVisitor classes implementing Visitor interface together form the Visitor Hierarchy.
  • Element is the base interface for the Element Hierarchy. All ConcreteElement classes implementing Element form the Element Hierarchy.
  • Each ConcreteVisitor implementation represents an operation to be performed on the classes in the Element Hierarchy.
  • Internally each ConcreteVisitor has a method corresponding to each of the ConcreteElement instances. These methods, named as processElement1(), processElement2() etc, contain the logic for applying the operation defined by ConcreteVisitor on that specific ConcreteElement.
  • Each ConcreteElement implements the acceptVisitor(Visitor) method inherited from the Element base interface which allows them to get hold of the specific ConcreteVisitor object corresponding to the operation.
  • Thus, to add a new operation on the elements of ElementHierarchy the following steps need to be followed -
    1. Create a ConcreteVisitor representing the new operation.
    2. In the new ConcreteVisitor implement methods processElement1(), processElement2() etc as per the logic of the new operation.
    3. Client needs to create instance of a ConcreteVisitor as per the operation it needs to perform on Element Hierarchy.
    4. As the client traverses the Element Hierarchy it invokes acceptVisitor() method on each of the ConcreteElement instances while passing to it the ConcreteVisitor instance.
    5. The ConcreteElement class then in its code invokes its named method, i.e. processElement1(), on the ConcreteVisitor it inherited.
Visitor Design Pattern Example in Java - Class Diagram
Visitor Design Pattern in Java Class Diagram
Explanation of Visitor Design Pattern's Java Example's Class Diagram The Java class diagram above depicts visitor pattern implemented for Tax Calculations in a Billing system where -
  • Biller is the client who calculates the total tax to be applied on the Products in a bill
  • There is a Product hierarchy with a Product base interface and has 2 types of Products - MRPProducts i.e. products sold at printed MRP and Vegetables which are sold by weight without printed MRPs.
  • All individual products implement the acceptVisitor() method where they invoke the appropriate method on the visitor named after them. For e.g.- MRPProduct's acceptVisitor() method invokes the calcTaxForMRPProducts() method on visitor object passed to it.
  • There is a TaxCalculator hierarchy with a TaxCalculationVisitor base interface and two child classes of TaxCalculationVisitor - VisitorForSalesTaxCalc & VisitorForVATCalc which contains the logic for applying SalesTax & VAT on the two types of Products defined in Product Hierarchy.
  • TaxCalculationVisitor & its children visitors have 2 methods corresponding to each of the product types - calcTaxForMRPProducts() & calcTaxForVegetables(). VisitorForSalesTaxCalc has its own logic of calculating the two types of taxes and so does VisitorForVATCalc.
  • So, when calculating sales tax Biller iterates over the products in the bill, passing them the VisitorForSalesTaxCalc object via the acceptVisitor() method. In the acceptVisitor() method the product implementation invokes the method on the visitor named after it(as explained above). The Biller iterates over all the products in the same way, calculates sales tax for all the products to get the total sales tax for the bill.
  • Similarly VAT is calculated by iterating and visiting all the products with object of corresponding VisitorForVATCalc class. This is how the visitor pattern works.
Summary In the above tutorial we looked at what is visitor design pattern where we saw its class diagram for a facade design pattern & its explanation. We then saw the class diagram for an example of visitor design pattern in Java & its explanation. This concludes the tutorial on visitor design pattern.