访问者模式(VISITOR),提供一个作用于某对象结构中各元素的操作表示,并使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作,属于对象行为型模式。使用Visitor模式,必须定义两个类层次:一个对应于接受操作的元素(Element层次),另一个对应于定义对元素的操作的访问者(Visitor层次)。给访问者类层次增加一个新的子类即可创建一个新的操作,但如果新增一个接受操作的元素,则需要修改Visitor及其子类实现,这是Visitor模式的最大缺点。Visitor模式在XML文档解析,编译器设计,复杂集合对象处理中得到一定的应用。
一、使用场景
1、对于一个包含很多具有不同接口的类对象的复杂对象结构,可以使用Visitor模式对它内部的类对象实施一些依赖于它们的具体类的操作。
2、需要对一个对象结构中的对象进行很多不同且不相关的操作,并要避免这些操作“污染”对象的类。Visitor模式使得我们可以将相关的访问操作集中起来定义在访问者类中,对象结构可以被多个不同的访问者类所使用,将对象本身与对象的访问操作分离。
3、定义对象结构的类(Element类层次)很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重新定义对所有访问者的接口,代价很大。
二、UML图

三、Java实现
package study.patterns.visitor;
import java.util.ArrayList;
import java.util.List;
/**
* 访问者模式:操作复杂对象结构的艺术
* @author qbg
*/
public class VisitorPattern {
public static void main(String[] args) {
StaffList staffList = new StaffList();
Teacher t1 = new Teacher("张三", 12, 95);
staffList.addStaff(t1);
Teacher t2 = new Teacher("李四", 8, 85);
staffList.addStaff(t2);
Student s1 = new Student("王五", 0, 80);
staffList.addStaff(s1);
Student s2 = new Student("赵六", 3, 93);
staffList.addStaff(s2);
AwardCheck srAward = new ScientificResearchAward();
System.out.println("=========评选科研奖===============");
staffList.accept(srAward);
System.out.println("=========评选优秀成绩奖===========");
AwardCheck oaAward = new OutstandingAchievementAward();
staffList.accept(oaAward);
}
}
/**
* 抽象元素类: 人员
*/
interface Staff{
public void accept(AwardCheck handler);
}
/**
* 具体元素类:教师
*/
class Teacher implements Staff{
private String name;
private int paperCount;//论文数
private int feedBackScore;//教学反馈分数
public Teacher(String name,int pagerCount,int feedBackScore){
this.name = name;
this.paperCount = pagerCount;
this.feedBackScore = feedBackScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPaperCount() {
return paperCount;
}
public void setPaperCount(int paperCount) {
this.paperCount = paperCount;
}
public int getFeedBackScore() {
return feedBackScore;
}
public void setFeedBackScore(int feedBackScore) {
this.feedBackScore = feedBackScore;
}
@Override
public void accept(AwardCheck handler) {
handler.visit(this); //调用访问者的访问方法
}
}
/**
* 具体元素类:学生
*/
class Student implements Staff{
private String name;
private int paperCount;//发表论文数
private int averageScore;//平均成绩
public Student(String name,int paperCount,int averageScore){
this.name = name;
this.paperCount = paperCount;
this.averageScore = averageScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPaperCount() {
return paperCount;
}
public void setPaPerCount(int paperCount) {
this.paperCount = paperCount;
}
public int getAverageScore() {
return averageScore;
}
public void setAverageScore(int averageScore) {
this.averageScore = averageScore;
}
@Override
public void accept(AwardCheck handler) {
handler.visit(this);//调用访问者的访问方法
}
}
/**
* 抽象访问者:奖励审批抽象接口
*/
interface AwardCheck{
public void visit(Teacher teacher);
public void visit(Student student);
}
/**
* 具体访问者:科研奖审批
*/
class ScientificResearchAward implement