Wzorzec projektowy odwiedzający należy do czynnościowych wzorców projektowych. Jego celem jest oddzielenie algorytmu od obiektu, na którym ów algorytm jest realizowany.
Na poniższym diagramie UML klasy Comment i Code dziedziczące po interfejsie iText mają zaimplementowaną metodę write, która to przyjmuje jako argument interfejs iCode. Interfejs ten jest dziedziczony przez klasy VBCode i CppCode mające zaimplementowaną metodę write w wersji przyjmującej jako argument referencje do obiektu klasy Code oraz w wersji przyjmującej jako argument obiekt klasy Comment. Interfejs iCode odwiedza obiekt klasy VBCode lub CppCode w celu wyświetlenia informacji w nim zawartych.
Przykładowa implementacja wzorca projektowego odwiedzający w C++
#include <iostream>
#include <string>
#include <vector>
class Code;
class Comment;
class iCode{
public:
virtual void write(Code &code) = 0;
virtual void write(Comment &comment) = 0;
virtual ~iCode(){}
};
class iText{
protected:
std::string text;
public:
iText(std::string text) : text(text){}
inline std::string getText() { return text; }
virtual void write(iCode* icode) = 0;
virtual ~iText(){}
};
class Code : public iText{
public:
Code(std::string text) : iText(text){}
virtual void write(iCode* icode){
icode->write(*this);
}
};
class Comment : public iText{
public:
Comment(std::string text) : iText(text){}
virtual void write(iCode* icode){
icode->write(*this);
}
};
class VBCode : public iCode{
public:
virtual void write(Code &code){
std::cout << "VB code: " << code.getText() << std::endl;
}
virtual void write(Comment &comment){
std::cout << "VB comment: " << comment.getText() << std::endl;
};
};
class CppCode : public iCode{
virtual void write(Code &code){
std::cout << "C++ code: " << code.getText() << std::endl;
}
virtual void write(Comment &comment){
std::cout << "C++ comment: " << comment.getText() << std::endl;
};
};
int main(){
std::vector<iText*> text;
text.push_back(new Comment("This is a line of comment in C++"));
text.push_back(new Code("int x = 0;"));
CppCode cppcode;
for(int i = 0; i < text.size(); i++){
text[i]->write(&cppcode);
}
while(!text.empty()){
delete text.back();
text.pop_back();
}
text.push_back(new Comment("This is a line of comment in VB"));
text.push_back(new Code("Dim x As Integer;"));
VBCode vbcode;
for(int i = 0; i < text.size(); i++){
text[i]->write(&vbcode);
}
while(!text.empty()){
delete text.back();
text.pop_back();
}
std::cin.get();
return 0;
}
Wynik działania powyższego kodu:
C++ comment: This is a line of comment in C++
C++ code: int x = 0;
VB comment: This is a line of comment in VB
VB code: Dim x As Integer;