访问者模式,就是我们已经有一系列的对象了,那么就可以使用一个visitor对象一次性遍历所有的对象,就好像这个visitor访问了所有这些对象一样,所以就叫访问者模式。
实现起来也很简单,就是三个基类,其他类都是这些基类的衍生类。
下面的Action类就是访问者类了,而Person类就是被访问的对象类,而House是一个接待容器,可以接待不同的Action类。
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Person;
class Action
{
public:
string present;
string gun;
virtual void drinkBeer(Person *p) = 0;
virtual void getAGun(Person *p) = 0;
};
class ActionOne:public Action
{
public:
ActionOne()
{
present = "Alcohol";
gun = "Laiser";
}
void drinkBeer(Person *p);
void getAGun(Person *p);
};
class ActionTwo:public Action
{
public:
ActionTwo()
{
present = "Beer";
gun = "Machine Gun";
}
void getAGun(Person *p);
void drinkBeer(Person *p);
};
class Person
{
public:
string something;
virtual void receivedVisitor(Action *visitor) = 0;
};
class Bill:public Person
{
public:
Bill()
{
something = "food";
}
void receivedVisitor(Action *visitor)
{
puts("\nVisitor to Bill bring :");
puts(visitor->present.c_str());
visitor->drinkBeer(this);
}
};
class Mark:public Person
{
public:
Mark()
{
something = "Weapon";
}
void receivedVisitor(Action *visitor)
{
puts("\nVisitor to Mark bring :");
puts(visitor->gun.c_str());
visitor->getAGun(this);
}
};
void ActionOne::drinkBeer(Person *p)
{
puts("Let's eat something");
puts(p->something.c_str());
}
void ActionOne::getAGun(Person *p)
{
puts("Let's gear up");
puts(p->something.c_str());
}
void ActionTwo::getAGun(Person *p)
{
puts("Let's gear up");
puts(p->something.c_str());
}
void ActionTwo::drinkBeer(Person *p)
{
puts("Let's eat something");
puts(p->something.c_str());
}
class House
{
protected:
vector<Person *> vps;
public:
void addPerson(Person *p)
{
vps.push_back(p);
}
void receiver(Action *visitor)
{
for (int i = 0; i < (int)vps.size(); i++)
{
vps[i]->receivedVisitor(visitor);
}
}
~House()
{
for (int i = 0; i < (int)vps.size(); i++)
{
delete vps[i];
}
}
};
int main()
{
House house;
house.addPerson(new Bill);
house.addPerson(new Mark);
ActionTwo gun;
ActionOne drink;
house.receiver(&gun);
house.receiver(&drink);
return 0;
}
运行: