Visitor Design Pattern

Looney Tunes Hello GIF by Looney Tunes World of Mayhem

Visitor Pattern is a behavioral design pattern, that helps you separate algorithms or new functionality you want to add to objects or classes.

What this means is that, if you have to introduce new functionality or new behavior to an object or class, you don’t have to change the Class definition.

Problem Statement

Let’s understand this pattern with help of one example problem

  • Consider you have to create an application which gets estimates for a different type of construction sites.
  • Based on what a builder wants to construct, he/she needs to enter details of the project and you will get different types of estimates.

Your application currently supports getting estimates for the following construction site: Home, Factory, Bridge

Everything was lovely and fairy, but one day your boss came with a new requirement, that he wants to add export Estimates to all PDF format functionality.

Need GIF by memecandy

Now you can add export to PDF format functionality in all your construction site classes (bridge, factory, house), but it is not a good idea:

  • You know such requests will keep on coming to modify existing classes to add new functionality. 
  • Over time these classes will become bloated and it will be hard to maintain such classes.
  • This also means every time you change the existing classes you have to re-test all these classes.
  • What about the design principle: Classes should be open for extension, but closed for modification.

Visitor Pattern to rescue

Show Off Super Hero GIF by CBeebies HQ

Visitor pattern suggests that:

  • You create a Visitor interface with abstract methods that represent new functionality to be added.
  • Provide new functionality that you have to provide as an implementation of the Visitor interface
  • Modify your existing classes (Bridge, Factory, House) just once to add a new method to them, which will take an object of Visitor type and call execute method present in it.

Pseudocode

If you find the above statements little gibberish, let’s look at this Pseudocode to understand it:

Step 1: Start with creating Visitor Interface

Interface Visitor {

	exportBridgeReport(Bridge object) 
	exportFactoryReport(Factory object)
	exportHouseReport(House object) 
}

Note: It may be hurting your eyes, why have I created multiple methods for each construction site. I am covering this at the end of the article.

Step 2: Create an implementation of Visitor

Class PdfExportVisitor implements Visitor {

	exportBridgeReport(Bridge object) { … }
	exportFactoryReport(Factory object) { … }
	exportHouseReport(House object) { … }
}

Step 3: Updating the existing classes:

Class Bridge implements ConstructionSite {
	…
	executeVisitor(Visitor v) {
		v.exportBridgeReport(this);
	}
}
Class Factory implements ConstructionSite {
	…
	executeVisitor(Visitor v) {
            v.exportFactoryReport(this);
	}
}
Class House implements ConstructionSite {

	…
	executeVisitor(Visitor v) {
            v.exportHouseReport(this);
	}
}

Are you thinking of improving this further (Coming back to the above note)?

You may think that the above implementation, can further be improved by having a single exportReport as an abstract method in the Visitor interface. And in its implementation class we can decide based on ConstructionSite real object, what behavior we need to provide.

Let’s write Pseudocode:

Interface Visitor {
	exportReport(ConstructionSite object);
}
Class PdfExportVisitor implements ReportVisitor {

	exportReport(ConstructionSite object) {

            if (object instanceof Bridge) 
                do something …
            else if (object instanceof Factory) 
                do something ….
            else if (object instanceof House) 
                do something 
    }
}

Visitor pattern discourages the above implementation, as over time the number of ConstructionSite type classes will increase, these if-else conditions will keep increasing. Hence the PdfExportVisitor code will become bloated and may not be that maintainable.

That’s why, as per Visitor pattern suggests that instead of putting conditions inside Visitor implementation, let’s have separate methods for each ConstructionSite and let the class (Bridge, house, factory) decide which method of the visitor to call.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s