Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use the Visitor Design Pattern? [closed]

I keep seeing references to the visitor pattern in blogs but I've got to admit, I just don't get it. I read the wikipedia article for the pattern and I understand its mechanics but I'm still confused as to when I'd use it.

As someone who just recently really got the decorator pattern and is now seeing uses for it absolutely everywhere I'd like to be able to really understand intuitively this seemingly handy pattern as well.

like image 366
George Mauer Avatar asked Oct 31 '08 23:10

George Mauer


People also ask

When should we use visitor design pattern?

Visitor design pattern is one of the behavioral design patterns. It is used when we have to perform an operation on a group of similar kind of Objects. With the help of visitor pattern, we can move the operational logic from the objects to another class.

What problems can the visitor design pattern solve?

The Visitor design pattern is one of the twenty-three well-known Gang of Four design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

When should design patterns not be used?

If a problem has two solutions, one that fits in ten lines of code, and another one with hundreds of lines of code along with a pattern, please consider not using the pattern. Their presence isn't a quality measurement.

Which design pattern can be used by Visitors to apply an operation over an object structure?

The Visitor pattern represents an operation to be performed on the elements of an object structure without changing the classes on which it operates.


2 Answers

I'm not very familiar with the Visitor pattern. Let's see if I got it right. Suppose you have a hierarchy of animals

class Animal {  }; class Dog: public Animal {  }; class Cat: public Animal {  }; 

(Suppose it is a complex hierarchy with a well-established interface.)

Now we want to add a new operation to the hierarchy, namely we want each animal to make its sound. As far as the hierarchy is this simple, you can do it with straight polymorphism:

class Animal { public: virtual void makeSound() = 0; };  class Dog : public Animal { public: void makeSound(); };  void Dog::makeSound() { std::cout << "woof!\n"; }  class Cat : public Animal { public: void makeSound(); };  void Cat::makeSound() { std::cout << "meow!\n"; } 

But proceeding in this way, each time you want to add an operation you must modify the interface to every single class of the hierarchy. Now, suppose instead that you are satisfied with the original interface, and that you want to make the fewest possible modifications to it.

The Visitor pattern allows you to move each new operation in a suitable class, and you need to extend the hierarchy's interface only once. Let's do it. First, we define an abstract operation (the "Visitor" class in GoF) which has a method for every class in the hierarchy:

class Operation { public:     virtual void hereIsADog(Dog *d) = 0;     virtual void hereIsACat(Cat *c) = 0; }; 

Then, we modify the hierarchy in order to accept new operations:

class Animal { public: virtual void letsDo(Operation *v) = 0; };  class Dog : public Animal { public: void letsDo(Operation *v); };  void Dog::letsDo(Operation *v) { v->hereIsADog(this); }  class Cat : public Animal { public: void letsDo(Operation *v); };  void Cat::letsDo(Operation *v) { v->hereIsACat(this); } 

Finally, we implement the actual operation, without modifying neither Cat nor Dog:

class Sound : public Operation { public:     void hereIsADog(Dog *d);     void hereIsACat(Cat *c); };  void Sound::hereIsADog(Dog *d) { std::cout << "woof!\n"; }  void Sound::hereIsACat(Cat *c) { std::cout << "meow!\n"; } 

Now you have a way to add operations without modifying the hierarchy anymore. Here is how it works:

int main() {     Cat c;     Sound theSound;     c.letsDo(&theSound); } 
like image 167
Federico A. Ramponi Avatar answered Nov 23 '22 00:11

Federico A. Ramponi


The reason for your confusion is probably that the Visitor is a fatal misnomer. Many (prominent1!) programmers have stumbled over this problem. What it actually does is implement double dispatching in languages that don't support it natively (most of them don't).


1) My favourite example is Scott Meyers, acclaimed author of “Effective C++”, who called this one of his most important C++ aha! moments ever.

like image 45
Konrad Rudolph Avatar answered Nov 23 '22 00:11

Konrad Rudolph