Visitor Design Pattern: Behavioral patterns

Share the Article

What is Visitor Design Pattern

Visitor design pattern is a type of behavioral design pattern which is mainly used for adding new operations to existing objects. This pattern acts on the existing objects therefore, it does not change existing hierarchy of the classes. Basically, the pattern creates new classes for adding new operations on existing objects.

Visitor pattern is based on visiting node or object concept. Therefore, older objects visit new classes in order to get new features.

Why

Lets us try to understand the need of visitor design pattern by taking an example of an entry screen application. This application enables entering data, like, text, icon, animation on a output screen. The application shall support following data:

  • Text.
  • Icon.
  • Animation .

Example without using Visitor Design Pattern

Below is the code snippet for the basic entry screen application :

#include<iostream> //Main header using namespace std;//for namespace class ScreenEntryComponent { }; class Text: ScreenEntryComponent { public: void showText() { cout<<"Basic text"<<endl; } }; class Icon: ScreenEntryComponent { public: void showIcon() { cout<<"Basic Icon"<<endl; } }; class Animation: ScreenEntryComponent { public: void showAnimation() { cout<<"Show Animation"<<endl; } }; int main() //Client-code { Text t1; Icon i1; Animation a1; t1.showText(); i1.showIcon(); a1.showAnimation(); return 0; }

As shown above, we are having ScreenEntryComponent class from which Text, Icon and Animation classes are derived. The client is creating Text, Icon and Animation objects and calling the respective show methods.

Suppose now, entry screen application needs to support below requirements also:

  • Requirement 1 – Festival effect
    • During festivals, the entry screen needs to show flickering text, flickering icon and flickering animation effects.
  • Requirement 2 – Monsoon effect
    • During monsoon season, the entry screen needs to show motion text, Watery icon and animations to show monsoon effects.

One way of doing this without Visitor pattern is to derive festival and monsoon effect for all derived classes. i.e., component text, Icon and animations.

Below is the class hierarchy’s with updated effects:

class FestivalText: public text; class FestivalIcon: public icon; class MonsoonText: public Text; so on....

Following are the drawbacks of above approach:

  • Code complexity increases many-fold due to effects.
  • In future, if more effects added, it becomes difficult to handle.

Therefore, for such application where we have existing objects such as:

  • Text
  • Icon
  • Animations

And we need to add more effects such as :

  • Festival
  • Monsoon etc.

Visitor pattern is the best fit.

How

Lets us try to update the above application with Visitor design pattern. We need to follow below rules for Visitor design pattern:

Create a Visitor class

Firstly, create a Visitor class which visits or all adds required objects. For instance, for the above application, VisitorEffect is the Visitor class. Derive all required effects, such as, festival and monsoon from VisitorEffect class.

class VisitorEffect //Visitor Class { }; class FestivalEffect: public VisitorEffect { }; class MonsoonEffect: public VisitorEffect { };

Visit( ) Method

Add visit( ) operation in visitor class for all existing objects. Visit interface will give provision to existing objects to use new operations.

class VisitorEffect { public: virtual void visit(Text *)=0; virtual void visit(Icon *)=0; virtual void visit(Animation *)=0; };

Accept( ) method in existing class to accept any visitors

Add accept( ) operation in ScreenEntryComponent class so that existing object accepts new Visitor class objects.

class ScreenEntryComponent { public: virtual void accept(VisitorEffect *v)=0; };

Below is the diagram:

visitor design pattern

Example using Visitor Design Pattern

Below is the updated entry screen application supporting all effects:

#include<iostream> //main header using namespace std;//for namespace class VisitorEffect; //Forward Declaration of Visitor class ScreenEntryComponent { public: virtual void accept(VisitorEffect *v)=0; }; class Text: public ScreenEntryComponent { public: void accept( VisitorEffect *v); void showText() { cout<<"Basic text"<<endl; } }; class Icon: public ScreenEntryComponent { public: void accept( VisitorEffect *v); void showIcon() { cout<<"Basic Icon"<<endl; } }; class Animation: public ScreenEntryComponent { public: void accept( VisitorEffect *v); void showAnimation() { cout<<"Show Animation"<<endl; } }; class VisitorEffect { public: virtual void visit(Text *)=0; virtual void visit(Icon *)=0; virtual void visit(Animation *)=0; }; class FestivalEffect: public VisitorEffect { public: void visit(Text *t1) { cout<<" Flickering Effect "; t1->showText(); } void visit(Icon *i1) { cout<<" Flickering Effect " ; i1->showIcon(); } void visit(Animation *a1) { cout<<" Flickering Effect "; a1->showAnimation(); } }; class MonsoonEffect: public VisitorEffect { public: void visit(Text *t1) { cout<<" Monsoon effect "; t1->showText(); } void visit(Icon *i1) { cout<<" Monsoon effect "; i1->showIcon(); } void visit(Animation *a1) { cout<<" Monsoon effect "; a1->showAnimation(); } }; void Text::accept( VisitorEffect *v) { v->visit(this); } void Icon::accept( VisitorEffect *v) { v->visit(this); } void Animation::accept( VisitorEffect *v) { v->visit(this); } int main() { ScreenEntryComponent *objects[] = { new Text(), new Icon(), new Animation() }; FestivalEffect fe; MonsoonEffect me; for (int i = 0; i <=2; i++) objects[i]->accept(&fe); for (int i = 0; i <=2; i++) objects[i]->accept(&me); return 0; }

As seen above, now with Visitor design pattern, we have not touched the existing objects. However, the existing objects can now print new effects. We have added VisitorEffect class, therefore, now, in future if we have to support more effects it is very easy to derive from VisitorEffect. All existing objects shall get new operations by visiting and accepting new VisitorEffect classes.

Pros and cons of Visitor Design Pattern

Pros

  • Firstly, it is very easy to add new operations on existing objects.
  • Secondly, any future enhancement are also easily possible.
  • Finally, the pattern is very useful when only few derived classes need to get new functionality. Therefore, base class need not provide a new central method in such cases.

Cons

  • Firstly, due to one more hierarchy of visitor class, the design may become more complex to understand.
  • Secondly, now, the client needs to interact with both visitor and existing objects also.

Main Funda: The visitor design pattern is useful to provide new feature in existing objects.

Advanced C++ Topics

Abstract Factory Design Pattern
Singleton Design Pattern
Factory Method Design Pattern
Builder Design Pattern
Adapter Design Pattern
Prototype Design Pattern
Facade Design Pattern
Bridge Design Pattern
Composite Design Pattern
Decorator Design Pattern
Template Design Pattern
Strategy Design Pattern

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *