访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的情况下,定义作用于这些元素的新的操作。
如果系统的数据结构是比较稳定的,但其操作(算法)是易于变化的,那么使用访问者模式是个不错的选择;如果数据结构是易于变化的,则不适合使用访问者模式。
基本原理:在被访问的类里添加一个对外提供接待访问者的接口
老师考核成绩大于等于 85 分或者学生考核成绩大于 90 分,可以获得成绩优秀奖;
老师发表论文数大于等于 10 篇或者学生发表论文数大于等于 5 篇,可以获得科研优秀奖;
上述例子中,学生和老师就是具体元素,因为他们的数据结构基本不变,但对数据结构的操作是多变的,一会评选成绩优秀奖,一会评选科研优秀奖,因此可以使用访问者模式解决。
抽象访问者,可以访问学生和老师
public interface Visitor {
/**
* 访问学生元素
*/
void visit(Student student);
/**
* 访问老师元素
*/
void visit(Teacher teacher);
}
具体访问者:评选成绩优秀奖
public class ScoreJudge implements Visitor {
private String awardWords = "%s的分数是%d,荣获了成绩优秀奖。";
@Override
public void visit(Student student) {
if(student.getScore() >= 90){
System.out.println(String.format(awardWords, student.getName(), student.getScore()));
}
}
@Override
public void visit(Teacher teacher) {
if(teacher.getScore() >= 85){
System.out.println(String.format(awardWords, teacher.getName(), teacher.getScore()));
}
}
}
具体访问者:评选科研优秀奖
public class ResearchJudge implements Visitor {
private String awardWords = "%s的论文数是%d,荣获了科研优秀奖。";
@Override
public void visit(Student student) {
if(student.getPaperCount() >= 5){
System.out.println(String.format(awardWords, student.getName(), student.getPaperCount()));
}
}
@Override
public void visit(Teacher teacher) {
if(teacher.getPaperCount() >= 10){
System.out.println(String.format(awardWords, teacher.getName(), teacher.getPaperCount()));
}
}
}
抽象元素,可以让 Visitor 访问
public interface Element {
/**
* 接收一个抽象访问者访问
*/
void accept(Visitor visitor);
}
具体元素:学生
public class Student implements Element{
private String name;
private Integer score;
private Integer paperCount;
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
//省略 getter、setter、全参构造方法
}
具体元素:老师
public class Teacher implements Element {
private String name;
private Integer score;
private Integer paperCount;
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
//省略 getter、setter、全参构造方法
}
对象结构
public class ObjectStructure {
/**
* 用于存放所有元素
*/
private List<Element> elements = new LinkedList<>();
/**
* 访问者访问元素的入口
*/
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
public void attach(Element e) {
elements.add(e);
}
public void detach(Element e) {
elements.remove(e);
}
}
测试类
public class Client {
@Test
public void test() {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Student("Jack(student)", 95, 4));
objectStructure.attach(new Student("Maria(student)", 85, 6));
objectStructure.attach(new Teacher("Mike(teacher)", 80, 9));
objectStructure.attach(new Teacher("Anna(teacher)", 85, 10));
objectStructure.accept(new ScoreJudge());
System.out.println("------------------------");
objectStructure.accept(new ResearchJudge());
}
}
运行结果
Jack(student)的分数是95,荣获了成绩优秀奖。
Anna(teacher)的分数是85,荣获了成绩优秀奖。
---------------------
Maria(student)的论文数是6,荣获了科研优秀奖。
Anna(teacher)的论文数是10,荣获了科研优秀奖。
优点:
缺点:
适用场景:
原文:https://www.cnblogs.com/songjilong/p/12784568.html