什么是访问者模式
定义:表示一个作用于其对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
可以对定义这么理解:有这么一个操作,它是作用于一些元素之上的,而这些元素属于某一个对象结构。同时这个操作是在不改变各元素类的前提下,在这个前提下定义新操作是访问者模式精髓中的精髓。
主要解决:稳定的数据结构和易变的操作耦合问题。就是把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
本质:预留通路,回调实现。它的实现主要就是通过预先定义好调用的通路,在被访问的对象上定义accept方法,在访问者的对象上定义visit方法;然后在调用真正发生的时候,通过两次分发的技术,利用预先定义好的通路,回调到访问者具体的实现上
实例
某高校奖励审批系统可以实现教师奖励和学生奖励的审批(AwardCheck),如果教师发表论文数超过10篇或者学生论文超过2篇可以评选科研奖,如果教师教学反馈分大于等于90分或者学生平均成绩大于等于90分可以评选成绩优秀奖,使用访问者模式设计该系统,以判断候选人集合中的教师或学生是否符合某种获奖要求。
uml类图
代码实现
package VisitorPattern;
//访问者模式
public interface People {
public void accept(AwardCheck check);
}
package VisitorPattern;
public class Student implements People {
int paperAmount;
double score;
String studentName;
public Student(String name,int paperAmount,double score){
this.studentName=name;
this.score=score;
this.paperAmount=paperAmount;
}
public int getPaperAmount() {
return paperAmount;
}
public void setPaperAmount(int paperAmount) {
this.paperAmount = paperAmount;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@Override
public void accept(AwardCheck check) {
check.visit(this);
}
}
package VisitorPattern;
public class Teacher implements People {
int paperAmount;
double feedbackScore;
String teacherName;
public Teacher(String name,int paperAmount,double feedbackScore){
this.teacherName=name;
this.feedbackScore=feedbackScore;
this.paperAmount=paperAmount;
}
public int getPaperAmount() {
return paperAmount;
}
public void setPaperAmount(int paperAmount) {
this.paperAmount = paperAmount;
}
public double getFeedbackScore() {
return feedbackScore;
}
public void setFeedbackScore(double feedbackScore) {
this.feedbackScore = feedbackScore;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
@Override
public void accept(AwardCheck check) {
check.visit(this);
}
}
package VisitorPattern;
//评审
public abstract class AwardCheck {
public abstract void visit(Teacher teacher);
public abstract void visit(Student student);
}
package VisitorPattern;
public class ScientificAwardCheck extends AwardCheck {
@Override
public void visit(Teacher teacher) {
if (teacher.paperAmount>10){
System.out.println(teacher.teacherName+"老师你好,你的论文数超过10篇可以评选优秀科研奖!");
}else{
System.out.println(teacher.teacherName+"老师你好,你的论文数没超过10篇不可以评选优秀科研奖!");
}
}
@Override
public void visit(Student student) {
if (student.paperAmount>2){
System.out.println(student.studentName+"同学你好,你的论文数大于2篇,你可以参与评选科研奖了!");
}else{
System.out.println(student.studentName+"同学你好,你的论文数小于2篇,你不可以参与评选科研奖!");
}
}
}
package VisitorPattern;
public class ScoreAwardCheck extends AwardCheck {
@Override
public void visit(Teacher teacher) {
if (teacher.feedbackScore>90){
System.out.println(teacher.teacherName+"老师你好,你的反馈积分大于90分,你可以参与评选优秀奖!");
}else{
System.out.println(teacher.teacherName+"老师你好,你的反馈积分小于90分,你不可以参与评选优秀奖!");
}
}
@Override
public void visit(Student student) {
if (student.score>90){
System.out.println(student.studentName+"同学你好,你的平均成绩大于90分,你可以参与评选优秀奖!");
}else{
System.out.println(student.studentName+"同学你好,你的平均成绩小于90分,你不可以参与评选优秀奖!");
}
}
}
package VisitorPattern;
import java.util.ArrayList;
import java.util.Iterator;
//申请人集合
public class candidateList {
private ArrayList list = new ArrayList();
public void accept(AwardCheck check){
Iterator i = list.iterator();
while (i.hasNext()){
((People)i.next()).accept(check);
}
}
public void addPerson(People people){
list.add(people);
}
public void removePerson(People people){
list.remove(people);
}
}
package VisitorPattern;
public class test {
public static void main(String[] args) {
People b1 = new Teacher("张三",12,89);
People b2 = new Student("李四",1,98);
candidateList list = new candidateList();
list.addPerson(b1);
list.addPerson(b2);
AwardCheck check1 = new ScientificAwardCheck();
AwardCheck check2 = new ScoreAwardCheck();
list.accept(check1);
System.out.println("==========");
list.accept(check2);
}
}
运行结果