Visitor

From Schmid.wiki
Jump to: navigation, search

Example

#include <iostream>
#include <vector>
using namespace std;

struct Orc; struct Human;

struct Character_visitor {
    virtual void visit(Orc& orc) = 0;
    virtual void visit(Human& human) = 0;
};

struct Character {
    Character(char *name) : name(name) {}
    virtual void accept(Character_visitor& cv) = 0;
    char *name;
};

struct Orc : public Character {
    Orc(char *name) : Character(name) {}
    virtual void accept(Character_visitor& cv) { cv.visit(*this); }
};

struct Human : public Character {
    Human(char *name) : Character(name) {}
    virtual void accept(Character_visitor& cv) { cv.visit(*this); }
};

class Info_visitor : public Character_visitor {
public:
    Info_visitor() : line(0) {}
    void visit(Orc& orc) {
        cout << ++line << ". Orc: " << orc.name << endl;
    }
    void visit(Human& human) {
        cout << ++line << ". Human: " << human.name << endl;
    }
private:
    int line; // visitor has state
};

main() {
    vector<Character *> characters;
    typedef vector<Character *>::iterator ci;

    characters.push_back(new Orc("Grok"));
    characters.push_back(new Human("Bob"));
    characters.push_back(new Orc("Gonk"));

    Info_visitor iv;

    for(ci i = characters.begin(); i != characters.end(); ++i)
        (*i)->accept(iv);
}

The visitable Character classes define the method for traversal. Here, the visitor only visits the objects themselves, but a tree-like hierarchy is easily established.

The fact that the visitor is an class, makes it possible to have a state in the visitor, enabling features such as "killing 1 Orc out of 10" :).

References

Personal tools