一、定义
表示一个施加于某对象结构中的各元素之上的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
二、解读
“某对象结构”,这个结构中可能会有很多不同类型的对象。针对不同对象会有不同的操作。
那么一般情况下,要操作这个对象结构中的不同对象,我们可能会遍历集合中的每个对象,然后根据每个对象的类型来做具体的操作。这会很复杂,因为我们一定会用很多if…else来检查对象类型。可想而知,代码一定会很杂乱。耦合性很强。
访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。
三、类图
四、结构
抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。它的方法个数理论上来讲与元素个数(Element的实现类个数)是一样的,从这点不难看出,访问者模式要求元素类的个数不能改变(不能改变的意思是说,如果元素类的个数经常改变,则说明不适合使用访问者模式)。
具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。其意义是指,每一个元素都要可以被访问者访问。
具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。
结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。
访问者模式主要分为两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,主要用于什么一些操作。一个是元素层次结构,提供了抽象元素和具体元素,主要用于声明Accept操作。
五、生活中的例子
一台电脑由很多部件组成,有显示屏、主机、键盘、鼠标等外设。不同身份的人对这台电脑的部件会有不同的操作。消费者可能就是简单地看看各个部件的价格、商标、参数。维修员则会对部件进行检查。
在这里,消费者和维修员就是具体访问者角色,显示屏、主机、键盘、鼠标等就是具体节点角色,电脑这一个整体就是结构对象角色。
此处用访问者模式,代码如下:
六、C++代码
(一)抽象节点
// 部件基类 Part.h
#ifndef VISITORDEMO_PART_H
#define VISITORDEMO_PART_H
class Visitor;
class Part{
public:
virtual void accept(Visitor *visitor) = 0;
};
#endif //VISITORDEMO_PART_H
(二)具体节点
// 显示屏类,具体节点。 Monitor.h
#ifndef VISITORDEMO_MONITOR_H
#define VISITORDEMO_MONITOR_H
#include "Part.h"
#include "Visitor.h"
#include <iostream>
using namespace std;
class Monitor: public Part {
private:
string brand;
float price;
public:
Monitor(string brand,float price);
void accept(Visitor *visitor) override ;
string getBrand();
float getPrice();
};
#endif //VISITORDEMO_MONITOR_H