81: Design Patterns: Visitor.

Take Up Code - A podcast by Take Up Code: build your own computer games, apps, and robotics with podcasts and live classes

Categories:

What is the visitor design pattern? The visitor behavioral pattern allows you to perform actions on a collection of different types where the actions depend on the types. It’s an alternative to using virtual methods and lets you add new actions without changing the types. This pattern represents an operation that can be performed on a collection of objects and allows new operations to be defined without changing the objects. Because all the items in a collection or in a composite need to share a common interface, from outside the collection, they all appear to be the same. If you have many operations that you want to perform on the objects in the collection and want the operations to be customized by the type of object, then you might start out by adding all these operations as virtual methods in the interface. This leads to a very complicated and wasteful design when you have many different operations. And as new operations are added, the interface and each of the object types need to change to support the new operation. This pattern works best when the type of objects in the collection remains small or at least fairly constant. If the type of objects is also growing or changing just like the operations, then this design pattern won’t help as much. This pattern is optimized to help you support many different types of operations and allow new operations to be added without needing to change a bunch of code in the object classes. Here’s how the visitor pattern is implemented with an example consisting of two object types and two operation types. You define a single method in the object interface called accept which takes a single parameter of a new interface called visitor. interface: objectInterface methods: accept(visitor) Then you define your concrete object types. concrete class: objectOne implements objectInterface concrete class: objectTwo implements objectInterface The visitor interface will have methods for each concrete object type. interface: visitor methods: visitObjectOne(objectOne) visitObjectTwo(objectTwo) And then you define concrete classes for each operation. These are the visitors. concrete class: operationOne implements visitor concrete class: operationTwo implements visitor Then when some code wants to perform operationOne on each of the objects in a collection, it iterates through each instance and calls accept and passes operationOne as the visitor. When a particular object instance, say objectTwo, has its accept method called, it calls back to the visitor through the object specific method and passes itself as the parameter. This ends up in operationOne’s implementation of the visitObjectTwo method. This pattern is able to match both the specific operation type with the specific object type. This is done through a double-dispatch where the first dispatch happens when the object’s virtual method is invoked and the second dispatch occurs when the visitor’s virtual method is invoked. The really nice thing about this pattern though is that because each object just calls back to the visitor, there’s no real code in the object. Anytime a new operation is needed, you just need to add a new concrete implementation of the visitor interface and all the existing object code can remain unchanged. If you’d like to read the book that describes this pattern along with diagrams and sample code, then you can find Design Patterns at the Resources page. You can find all my favorite books and resources at this page to help you create better software designs. Listen to the full episode for more or read the full transcript below. Transcript The basic description says that this pattern represents an operation that can be performed on a collection of objects and allow new operations to be defined without changing the objects. There are all kinds of collections and episodes 39 through 44 describe just a few. And episode 66 describes the composite structural pattern which allows you