1、概述
访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。
2、使用场景
1)如果你需要对一个复杂对象结构 (例如对象树) 中的所有元素执行某些操作, 可使用访问者模式。
2)可使用访问者模式来清理辅助行为的业务逻辑。 该模式会将所有非主要的行为抽取到一组访问者类中, 使得程序的主要类能更专注于主要的工作。
3)当某个行为仅在类层次结构中的一些类中有意义, 而在其他类中没有意义时, 可使用该模式。你可将该行为抽取到单独的访问者类中, 只需实现接收相关类的对象作为参数的访问者方法并将其他方法留空即可。
3、实例
有以下场景:
有一所学校,有校长、老师、学生等角色,学校以外还有家长。
家长关注班级内学生的排名情况。
校长关注班级在内的升学率情况。
访问者:校长、家长
被访问者:老师、学生
定义用户接口:
/**
* 人员接口
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public interface User {
/**
* 查询
*/
void accept(Visitor visitor);
}
定义老师:
/**
* 教师类
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public class Teacher implements User {
/**
* 姓名
*/
private String name;
/**
* 班级
*/
private String theClass;
/**
* 升学率
*/
private double graduationRates;
public Teacher(String name, String theClass, double graduationRates) {
this.name = name;
this.theClass = theClass;
this.graduationRates = graduationRates;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTheClass() {
return theClass;
}
public void setTheClass(String theClass) {
this.theClass = theClass;
}
public double getGraduationRates() {
return graduationRates;
}
public void setGraduationRates(double graduationRates) {
this.graduationRates = graduationRates;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
定义学生:
/**
* 学生
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public class Student implements User {
/**
* 姓名
*/
private String name;
/**
* 班级
*/
private String thClass;
/**
* 排名
*/
private Integer rank;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getThClass() {
return thClass;
}
public void setThClass(String thClass) {
this.thClass = thClass;
}
public Integer getRank() {
return rank;
}
public void setRank(Integer rank) {
this.rank = rank;
}
public Student(String name, String thClass, Integer rank) {
this.name = name;
this.thClass = thClass;
this.rank = rank;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
定义访问者接口:
/**
* 访问者
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public interface Visitor {
/**
* 访问教师
* @param user
*/
void visit(Teacher user);
/**
* 访问学生
* @param user
*/
void visit(Student user);
}
定义校长:
/**
* 校长访问者
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public class HeadMaster implements Visitor {
@Override
public void visit(Teacher user) {
System.out.println("--------校长访问------------");
System.out.println("教师姓名:" + user.getName());
System.out.println("班级:" + user.getTheClass());
System.out.println("升学率为:" + user.getGraduationRates());
}
@Override
public void visit(Student user) {
System.out.println("----------校长访问----------");
System.out.println("学生姓名:" + user.getName());
System.out.println("排名:" + user.getRank());
System.out.println("班级:" + user.getThClass());
}
}
定义家长:
/**
* 家长访问者
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public class Parents implements Visitor {
@Override
public void visit(Teacher user) {
System.out.println("--------家长访问------------");
System.out.println("教师姓名:" + user.getName());
System.out.println("班级:" + user.getTheClass());
System.out.println("升学率为:" + user.getGraduationRates());
}
@Override
public void visit(Student user) {
System.out.println("----------家长访问----------");
System.out.println("学生姓名:" + user.getName());
System.out.println("排名:" + user.getRank());
System.out.println("班级:" + user.getThClass());
}
}
测试类:
/**
* 测试类
* @date: 2021/1/26
* @author weirx
* @version 3.0
*/
public class TestDemo {
public static void main(String[] args) {
Teacher teacher = new Teacher("张老师", "一班", 0.99);
Student student = new Student("小张", "一班", 8);
HeadMaster headMaster = new HeadMaster();
student.accept(headMaster);
teacher.accept(headMaster);
Parents parents = new Parents();
student.accept(parents);
teacher.accept(parents);
}
}
结果:
----------校长访问----------
学生姓名:小张
排名:8
班级:一班
--------校长访问------------
教师姓名:张老师
班级:一班
升学率为:0.99
----------家长访问----------
学生姓名:小张
排名:8
班级:一班
--------家长访问------------
教师姓名:张老师
班级:一班
升学率为:0.99
4、分析

整体的访问者结构如上图所示。
1)顶层访问者接口,分别定义访问不同对象的访问方法vistor,真正的访问者实现并重写visit方法。
2)顶层的元素对象接口,也就是被访问者。其核心方法就是accept(Vistor vistor),正正的元素实现并重写其accept方法。
3)客户端使用元素的accept去调用访问者模式。
5、总结
优点:
1) 开闭原则。 你可以引入在不同类对象上执行的新行为, 且无需对这些类做出修改。
2)单一职责原则。 可将同一行为的不同版本移到同一个类中。
缺点:
1)每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者。
2)在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限。
网友评论