Visitor design pattern for beginners.

Background –

I hope you have remembered implicit and explicit trusting. If not, then please go through this link. Visitor design pattern uses explicit trusting. It means an external system will share its signature and you (the class designer) have to make a decision, whether to accept it or not, once you accept it, the external system has authority to change the state of your object.

Training programs are a perfect example of the visitor design pattern. Where you will decide whether to take the training based on the teacher’s signature (identity or popularity). Once you have accepted training, the teacher will ask, your current knowledge on a particular topic. Which is nothing but your private information (or say internal state of the object), then the trainer will change (improve) your knowledge on the same topic through his/her training.

Here we are talking about exposing the object’s private information with the external system. 

Now take trainer as a visitor object and student as element object. We will have many trainers (visitor object) for different subject, and we also have many students (element object) subjects. That is why we have an abstract visitor class and its different concrete implementations.


Now understand the concept, teaching is not the behavior of the student, but there is a need for behavior changes in many student objects (become more proficient in subject X). So we use visitor object to make the changes.

Why do we need the visitor design pattern?


Think, there is a need for behavioral changes (or say new requirements on old behavior) for your class. You are looking out away, where other classes can do it for you, so that you can achieve that behavioral change, without having structural changes in your class. Or say without modifying (or adding more complexity, or making it more dirty) class, achieve behavioral change.

UML Structure -

visitor DP
UML structure of visitor design pattern

Different components of UML structure -

  • Visitor - it is an interface class, which will define visit API. Concrete implementation class will implement it.
  • Concrete visitor - implementation of APIs declared in visitor interface.
  • Element - this will give a general interface for all classes who are going to implement visitor, through accept API call. So all desire classes shall get inherited from it.
  • Concrete element - is your real implementation classes, which will contain business logic in it.

C++ Example -

visitor DP
Example of visitor design pattern (Click on picture to see zoom view)

#include<iostream>
using namespace std;

class DepartmentX;
class DepartmentY;

class Visitor 
{
  public: 
    virtual void Visit(DepartmentX& ) = 0; 
    virtual void Visit(DepartmentY& ) = 0;
};
class Employee 
{
  public:
    virtual void Accept(class Visitor *externalTrainer) = 0;
};
class DepartmentX : public Employee 
{
  public:
    void Accept(Visitor *externalTrainer)
    {
      externalTrainer->Visit(*this);
    }
    void ImproveKnowledge()
    {
      cout<<"Improve knowledge "<<endl;
    }
};
class DepartmentY : public Employee 
{
  public:
    void Accept(Visitor *externalTrainer)
    {
      externalTrainer->Visit(*this);
    }
    void ImproveKnowledge()
    {
      cout<<"Improve knowledge "<<endl;
    }
};
//--------------------------------------------------------------------------------------------------
// Class 
class CPPTrainer : public Visitor 
{
  public:
    void Visit(DepartmentX& dept)
    {
      dept.ImproveKnowledge();
      cout<<"Improving CPP knowledge of DepartmentX"<<endl;
    }
    void Visit(DepartmentY& dept)
    {
      dept.ImproveKnowledge();
      cout<<"Improving CPP knowledge of DepartmentY"<<endl;
    }
};

//--------------------------------------------------------------------------------------------------
// Class 
class JavaTrainer : public Visitor 
{
  public:
    void Visit(DepartmentX& dept)
    {
      dept.ImproveKnowledge();
      cout<<"Improving Java knowledge of DepartmentX"<<endl;
    }
    void Visit(DepartmentY& dept)
    {
      dept.ImproveKnowledge();
      cout<<"Improving Java knowledge of DepartmentY"<<endl;
    }
};
/*
#######################################################################################
#########  __  __       _        ######################################################
######### |  \/  | __ _(_)_ __   ######################################################
######### | |\/| |/ _` | | '_ \  ######################################################
######### | |  | | (_| | | | | | ######################################################
######### |_|  |_|\__,_|_|_| |_| ######################################################
#######################################################################################
*/
int main(int argc, char** argv) 
{
  Employee *pEmployee[] = {new DepartmentX, new DepartmentY};
  Visitor *pTrainers[] = {new CPPTrainer, new JavaTrainer};
  //Improving CPP knowledge of All department 
  for(int index = 0; index < 2; index++) 
  {
    pEmployee[index]->Accept(pTrainers[0]);
  }
  //Improving Java knowledge of All department
  for(int index = 0; index < 2; index++) 
  {
    pEmployee[index]->Accept(pTrainers[1]);
  }

  delete [] pEmployee;
  delete [] pTrainers;

  return 0;
}
///////////////////////////////////////////////////////////////////-------------OutPut
/*
kbaghel@MSDN_L7-5CG5111 /home/kbaghel/dev/github/DesignPatterns/03LLD-GoF_Patterns/behavioral/visitor/src/my
$ ./a.exe
Improve knowledge
Improving CPP knowledge of DepartmentX
Improve knowledge
Improving CPP knowledge of DepartmentY
Improve knowledge
Improving Java knowledge of DepartmentX
Improve knowledge
Improving Java knowledge of DepartmentY

*/

Thanks for reading it. To learn more about design patterns and basic design principles, please see my web page.

Comments

Popular posts from this blog

Non-virtual interface idiom (NVI)

Architectural patterns => Mud to structure => layers.

Architectural style -> Adoptable system -> Reflection.