Object-oriented pro­gram­ming (OOP), which is con­sid­ered a subfield of im­per­a­tive pro­gram­ming, has taken on a lot of meaning over the last few years. The option to define all com­po­nents of a software project as objects that behave dif­fer­ent­ly depending on their class has some distinct ad­van­tages over other types of pro­gram­ming – a big one is the ability to easily reuse already coded parts of the program. For de­vel­op­ers, this is one of the strongest arguments in favor of OOP.

This capacity for reuse, as well as tips on how to make im­ple­ment­ing, adapting, and testing created objects even easier, was all explained in the book Design Patterns: Elements of Reusable Object-Oriented Software published by the “Gang of Four” de­vel­op­ers. One of the over 20 different design patterns in this book is the “visitor pattern” or “visitor design pattern”, which we will explain in detail over the next sections.

What is a visitor pattern?

The visitor pattern or visitor design pattern is a pattern that will separate an algorithm from the object structure on which it operates. It describes a way to add new op­er­a­tions to existing object struc­tures without modifying the struc­tures them­selves. This char­ac­ter­is­tic makes visitor patterns a way to implement the open/closed principle (OCP). This principle of object-oriented software de­vel­op­ment states that each software entity – such as modules, classes or functions – should be si­mul­ta­ne­ous­ly open for extension but closed for mod­i­fi­ca­tion.

The visitor pattern is one of the 23 design patterns (within the category of be­hav­ioral patterns) described and published by the computer sci­en­tists Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides in 1994. Col­lec­tive­ly, these de­vel­op­ers are known as the “Gang of Four” (or GoF for short), which led to these patterns being referred to as the GoF design patterns.

What does the visitor design pattern do?

If an object structure is made of several, unrelated classes, it’s highly in­con­ve­nient for de­vel­op­ers to have to create a new subclass for each operation if they happen to need new op­er­a­tions often. The result of coding like this would be a system with a host of different entangled classes that is not only difficult to un­der­stand, but also hard to manage and edit if necessary. The biggest advantage of a visitor pattern is that the “visitor” lets you add new, virtual functions to a class family without having to modify any of the classes them­selves.

Note

Virtual functions (or methods) define target functions for which the target may be unknown at the time of coding. They are an important tool in object-oriented systems.

A visitor design pattern lets a “visitor object” be defined sep­a­rate­ly, with the goal of im­ple­ment­ing an operation to be performed on one or several elements of the object structure. Clients that access the object structure call the dis­patch­ing operation accept(visitor) on an element that delegates the request to the accepted visitor object. The visitor object can then perform that operation on the element.

Graphical example of a visitor pattern (UML diagram)

The con­nec­tion between available elements and linked visitor objects using a visitor design pattern is best demon­strat­ed graph­i­cal­ly in order to depict all re­la­tion­ships and exchanges in a the­o­ret­i­cal object-oriented system. The best set-up for this purpose is the Unified Modeling Language (UML), which we chose to use in the following class diagrams for our visitor pattern.

The pros and cons of the visitor pattern

A visitor pattern is a pre-made, well-func­tion­ing way to extend already existing entities in an object-oriented system. Adding a new operation can be done easily by simply defining the new visitor. This also allows all func­tion­al code to be cen­tral­ized. Im­ple­ment­ing any new op­er­a­tions is done centrally in the visitor class only, and the rest of the classes don’t need to be touched. The biggest advantage of a program using a visitor design pattern can be boiled down to the fact that the existing source code doesn’t have to be con­stant­ly adapted to new objects used. Instead, the logic is split between the visitors and visitor classes that act as stand-ins.

Of course, visitor design patterns are not perfect in all respects. Anyone wanting to work with this pattern needs to bear in mind that even slight changes to an element class generally mean that related visitor classes also have to be adjusted. There’s no way around the extra work when in­tro­duc­ing new elements at a later date, as they require the addition of visit() methods which in turn have to be added into the Con­crete­Vis­i­tor classes. The fantastic pos­si­bil­i­ties for software entity ex­ten­sions are therefore linked to a non-neg­li­gi­ble amount of effort.

How to use a visitor pattern

A visitor pattern can con­sid­er­ably simplify recurring tasks in software de­vel­op­ment. De­vel­op­ers who work with object-oriented systems should def­i­nite­ly consider reckoning with this design pattern. Since its design in 1994, the visitor pattern has become a big player in the pro­gram­ming scene, and it can prove useful re­gard­less of the software project at hand. There are also no real re­stric­tions in terms of the pro­gram­ming language you want to use, as long as you remember that it works best in object-oriented paradigms.

Popular languages for which visitor patterns can play an important role include:

  • C++
  • C#
  • Java
  • PHP
  • Python
  • JavaScript
  • Golang
iueor-qViR4.jpg To display this video, third-party cookies are required. You can access and change your cookie settings here.

Practical example of how to use a visitor pattern

We ap­pre­ci­ate that it’s not that easy to un­der­stand the use and point of a visitor pattern, but anyone learning to code today will certainly come into contact with this pattern.

For a simple-to-grasp analogy from a real-world situation, visitor patterns are often demon­strat­ed using cab rides. Let’s assume that a customer calls a cab to take them to their front door. The customer gets into the “visiting car”, but it’s the cab (or rather, the driver) that is fully in control of trans­port­ing the person.

Shopping in a su­per­mar­ket is another common example to explain how visitor patterns work. The person doing their grocery shopping puts every­thing they want in their shopping cart, which can be con­sid­ered a set of elements from the object structure. The cashier then acts like a visitor, scanning prices and/or weighing each in­di­vid­ual shopping item (i.e., element) to calculate the total cost.

Example code for a visitor pattern (PHP)

The following code is a simple, basic use of a visitor pattern in PHP.

return 'B';
	}
	public function getData() {
		return $this->the_data;
	}
	public function accept(Visitor $visitor) {
		$visitor-> VisitFromElementB($this);
	}
}
abstract class Visitor {
	abstract function VisitFromElementA(ElementA $elem);
	abstract function VisitFromElementB(ElementB $elem);
}
class Visitor1 extends Visitor {
	private $characteristics;
	public function getCharacs() {
		return $this->characteristics;
	}
	public function VisitFromElementA(ElementA $elem) {
		$this->characteristics = 'Info:'.$elem->getInfo();
	}
	public function VisitFromElementB(ElementB $elem) {
		$this->characteristics = 'DATA:'.$elem->getData().'!!';
	}
}
function Test() {
	write_line('Teststart');
	// Objectstructure
	$elements = array (
		new ElementA('Hello', 'New!!'),
		new ElementB('Finally.'),
	);
	$vis1 = new Visitor1();
	foreach ($elements as $element) {
		$element->accept($vis1);
		write_line('After visit from Element '.$element->getName().': '.$vis1-			>getCharacs());
}
}
function write_line($text) {
	print $text.'<br>';
}
Test();

The output for this example code snippet is as follows:

Teststart
After visit from Element A: Info:[Hello--New!!]
After visit from Element B: DATA:(Finally.)!!
Go to Main Menu