1.访问者模式的定义
访问者模式的官方定义,就是表示一个作用于某对象结构的各元素的操作,它使你可以在不改变各元素的前提下,定义作用于这些元素的操作。这句话的意思就是,将对象结构这一块的数据结构Element作为一个整体,通过一个结构对象ObjectStructure封装起来;同时访问者Visitor定义一个抽象类,在其内部定义针对这块数据结构中每种结构的执行方式,其通过ObjectStructure的高级接口,实现对这一块所有/部分数据结构进行访问。而根据对访问者Visitor抽象类的实例方式不同,对于这些数据结构元素Element的操作方式也不尽相同。
所以总结来说,数据结构元素Element类中提供进行操作的接口,而访问者Visitor中定义对于不同元素Element类的操作接口,不同的访问者Visitor实例类的实现方式不同,则对于同种Element元素类的操作方式自然也就不同了。
2.访问者模式的类图
通过类图可知,访问者模式中,客户端Client可调用的类仅为Visitor访问者类,以及ObjectStructure结构对象类。其中,访问者类Visitor中定义了所有具体元素类ConcreteElement的接口,其通过子类ConcreteVisitor来实现接口的实例化操作,并由此实现子类对于不同ConcreteElement元素类的不同操作;而ObjectStructure结构对象类为一个高级类,其内部封装了所有的ConcreteElement元素类,从而实现对于所有元素的增删使用等操作功能。具体如下:
- Visitor访问者类:这是一个抽象类,针对所需访问的所有ConcreteElement实例类均提供了对应的接口;
- ConcreteVisitor实例类:其继承自Visitor访问者类,用于实现其定义的对于所有ConcreteElement实例元素类的访问接口,由于不同ConcreteVisitor实例类的实现方式不同,从而使得不同访问者对于ConcreteElement实例元素类的访问权限也不相同;
- Element元素类:这是一个抽象类,其中定义了用于接受访问者Visitor的接口Accept;
- ConcreteElement元素实例类:其继承自Element元素类,用于实现其定义的接口Accept,该接口的实现通常为调用访问者Visitor的接口中,对应当前ConcreteElement元素实例类的接口。同时,其中仍可以加入诸如获取时间,获取访问者姓名的等功能;
- ObjectStructure结构对象类:其内部可以存储一个或多个Element元素类,并在其内部定义高级接口,实现对于Element元素类的增删、使用等功能;
- Client客户端:其定义具体的访问者,并使用ObjectStructure结构对象类,在ObjectStructure结构对象类中调用所需使用的Element元素类,使用客户端所定义的访问者类对其进行访问。
3.访问者模式的代码实现
本例中选用了一个Restaurant作为ObjectStructure结构对象类,其内部有多种RestaurantPart作为Element元素类,其中具体的ConcreteElement元素实例类为饭店中的大厅Hall、厨房Kitchen以及办公室Office。而访问者类Visitor为典型定义,其ConcreteVisitor实例类对应的是饭店的顾客Guest、厨师Cook以及经理Manager。
对于本例的实际操作,即定义三种类型(顾客Guest、厨师Cook以及经理Manager)的访问者Visitor,与分为三种类型(大厅Hall、厨房Kitchen以及办公室Office)的五个元素,将元素定义完成后存入结构对象类(Restaurant)中,通过调用Restaurant中的AccepAll接口,实现所有顾客对饭店中所有元素的访问尝试。
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Visitor;
class Hall;
class Kitchen;
class Office;
class RestaurantPart
{
public:
RestaurantPart(string name) : m_name(name) {}
string getName() { return m_name; }
virtual void Accept(Visitor *) = 0;
protected:
string m_name;
};
class Visitor
{
public:
Visitor(string name) : m_name(name) {}
virtual void VisitHall(Hall* systempart) = 0;
virtual void VisitKitchen(Kitchen* systempart) = 0;
virtual void VisitOffice(Office* systempart) = 0;
string getName() { return m_name; }
protected:
string m_name;
};
class Hall : public RestaurantPart
{
public:
Hall(string name) : RestaurantPart(name){}
void Accept(Visitor *visitor)
{
cout << "visitor " << visitor->getName() << " trying to visit the Hall named " << m_name << endl;
visitor->VisitHall(this);
}
};
class Kitchen : public RestaurantPart
{
public:
Kitchen(string name) : RestaurantPart(name) {}
void Accept(Visitor *visitor)
{
cout << "visitor " << visitor->getName() << " trying to visit the Kitchen named " << m_name << endl;
visitor->VisitKitchen(this);
}
};
class Office : public RestaurantPart
{
public:
Office(string name) : RestaurantPart(name) {}
void Accept(Visitor *visitor)
{
cout << "visitor " << visitor->getName() << " trying to visit the Office named " << m_name << endl;
visitor->VisitOffice(this);
}
};
class Guest : public Visitor
{
public:
Guest(string name) : Visitor(name) {}
void VisitHall(Hall* systempart) override
{
cout << "Welcome to visit the Hall named " << systempart->getName() << endl;
}
void VisitKitchen(Kitchen* systempart) override
{
cout << "Sorry! " << m_name << " can't enter the Kitchen named " << systempart->getName() << endl;
}
void VisitOffice(Office* systempart) override
{
cout << "Sorry! " << m_name << " can't enter the Office named " << systempart->getName() << endl;
}
};
class Cook : public Visitor
{
public:
Cook(string name) : Visitor(name) {}
void VisitHall(Hall* systempart) override
{
cout << "Welcome to visit the Hall named " << systempart->getName() << endl;
}
void VisitKitchen(Kitchen* systempart) override
{
cout << "Welcome to visit the Kitchen named " << systempart->getName() << endl;
}
void VisitOffice(Office* systempart) override
{
cout << "Sorry! " << m_name << " can't enter the Office named " << systempart->getName() << endl;
}
};
class Manager : public Visitor
{
public:
Manager(string name) : Visitor(name) {}
void VisitHall(Hall* systempart) override
{
cout << "Welcome to visit the Hall named " << systempart->getName() << endl;
}
void VisitKitchen(Kitchen* systempart) override
{
cout << "Welcome to visit the Kitchen named " << systempart->getName() << endl;
}
void VisitOffice(Office* systempart) override
{
cout << "Welcome to visit the Office named " << systempart->getName() << endl;
}
};
class Restaurant
{
public:
Restaurant() { m_restaurantpart_list.clear(); }
void insert(RestaurantPart* restaurantpart)
{
m_restaurantpart_list.insert({ restaurantpart->getName(),restaurantpart });
}
void remove(RestaurantPart* restaurantpart)
{
m_restaurantpart_list.erase(restaurantpart->getName());
}
RestaurantPart* use(string name)
{
return m_restaurantpart_list.at(name);
}
void AcceptAll(Visitor* vistor)
{
for (auto &s : m_restaurantpart_list)
s.second->Accept(vistor);
}
private:
map<string, RestaurantPart*> m_restaurantpart_list;
};
int main()
{
//1.Visitor,饭店部门,饭店的定义与赋值
Visitor* GuestMike = new Guest("GuestMike");
Visitor* CookJack = new Cook("CookJack");
Visitor* ManagerLinda = new Manager("ManagerLinda");
RestaurantPart* FirstHall = new Hall("FirstHall");
RestaurantPart* SecondHall = new Hall("SecondHall");
RestaurantPart* FirstKitchen = new Kitchen("FirstKitchen");
RestaurantPart* SecondKitchen = new Kitchen("SecondKitchen");
RestaurantPart* BossOffice = new Office("BossOffice");
Restaurant* CrisCloseDoor = new Restaurant;
CrisCloseDoor->insert(FirstHall);
CrisCloseDoor->insert(SecondHall);
CrisCloseDoor->insert(FirstKitchen);
CrisCloseDoor->insert(SecondKitchen);
CrisCloseDoor->insert(BossOffice);
//2.测试
cout << "***** GuestMike 全部访问 *****" << endl;
CrisCloseDoor->AcceptAll(GuestMike);
cout << "***** CookJack 全部访问 *****" << endl;
CrisCloseDoor->AcceptAll(CookJack);
cout << "***** ManagerLinda 全部访问 *****" << endl;
CrisCloseDoor->AcceptAll(ManagerLinda);
delete GuestMike;
delete CookJack;
delete ManagerLinda;
delete FirstHall;
delete SecondHall;
delete FirstKitchen;
delete SecondKitchen;
delete BossOffice;
}