It is often require to separate an algorithms from the data it operates on.
For example say that we have some inter process communication messages that needs to be sent out from a TCP channel.
The message is the parent class and different messages are derived from this class.
The sub-message class object that has some member variables that are used to pack the real messages to be sent out.
The straightforward way of doing this is to have a virtual function pack() defined in the message class itself and implement it in every sub-message class and call it whenever we need the message to be generated.
However this is not that efficient because if we need to change the structure or the format of the messages that we need to send out, the pack () of the that specific class should be modified.
If all messages require a addition of a different field all messages have to be changed.
Not if you have introduced the visitor pattern. Compare the visitor pattern with the standard approach. First off the bad example followed by the same thing done using the visitor pattern.
For example say that we have some inter process communication messages that needs to be sent out from a TCP channel.
The message is the parent class and different messages are derived from this class.
The sub-message class object that has some member variables that are used to pack the real messages to be sent out.
The straightforward way of doing this is to have a virtual function pack() defined in the message class itself and implement it in every sub-message class and call it whenever we need the message to be generated.
However this is not that efficient because if we need to change the structure or the format of the messages that we need to send out, the pack () of the that specific class should be modified.
If all messages require a addition of a different field all messages have to be changed.
Not if you have introduced the visitor pattern. Compare the visitor pattern with the standard approach. First off the bad example followed by the same thing done using the visitor pattern.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <list> | |
using namespace std; | |
class Employee { | |
public: | |
virtual string reportQtdHoursAndPay() = 0; | |
}; | |
class HourlyEmployee : public Employee { | |
public: | |
virtual string reportQtdHoursAndPay() { | |
//generate the line for this hourly employee | |
string report = "Generated report line for Hourly Employee"; | |
return report; | |
} | |
}; | |
class SalariedEmployee : public Employee { | |
public: | |
virtual string reportQtdHoursAndPay() { | |
string report = "Generated report line for Salaried Employee"; | |
return report; | |
} // do nothing | |
}; | |
int main() | |
{ | |
std::list<Employee*> lst_Employees; | |
HourlyEmployee he1,he2; | |
SalariedEmployee se1,se2; | |
lst_Employees.push_back(&he1); | |
lst_Employees.push_back(&he2); | |
lst_Employees.push_back(&se1); | |
lst_Employees.push_back(&se2); | |
for (std::list<Employee*>::iterator it=lst_Employees.begin(); it != lst_Employees.end(); ++it) | |
std::cout << (*it)->reportQtdHoursAndPay() << std::endl; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example program | |
#include <iostream> | |
#include <string> | |
#include <list> | |
using namespace std; | |
class HourlyEmployee; | |
class SalariedEmployee; | |
class EmployeeVisitor { // holds the algorithm | |
public: | |
virtual void visit(HourlyEmployee* he) = 0; | |
virtual void visit(SalariedEmployee* se) = 0; | |
}; | |
class Employee { | |
public: | |
virtual void accept(EmployeeVisitor* p) = 0; | |
}; | |
class HourlyEmployee : public Employee { | |
public: | |
virtual void accept(EmployeeVisitor* p) { | |
//generate the line for this hourly employee | |
//string report = "Generated report line for Hourly Employee"; | |
//return report; | |
p->visit(this); | |
} | |
}; | |
class SalariedEmployee : public Employee { | |
public: | |
virtual void accept(EmployeeVisitor* p) { | |
//string report = "Generated report line for Salaried Employee"; | |
//return report; | |
p->visit(this); | |
} // do nothing | |
}; | |
class QtdHoursAndPayReport : public EmployeeVisitor { | |
public: | |
void visit(HourlyEmployee* he) { | |
// generate the line of the report. | |
cout << "Generated report line for Hourly Employee" << endl; | |
} | |
void visit(SalariedEmployee* se) { | |
cout << "Generated report line for Salaried Employee" << endl; | |
} | |
}; | |
int main() | |
{ | |
std::list<Employee*> lst_Employees; | |
HourlyEmployee he1,he2; | |
SalariedEmployee se1,se2; | |
lst_Employees.push_back(&he1); | |
lst_Employees.push_back(&he2); | |
lst_Employees.push_back(&se1); | |
lst_Employees.push_back(&se2); | |
QtdHoursAndPayReport* v = new QtdHoursAndPayReport(); | |
for (std::list<Employee*>::iterator it=lst_Employees.begin(); it != lst_Employees.end(); ++it) | |
(*it)->accept(v); | |
return 0; | |
} |
Comments
Post a Comment