访问者模式(Visitor)
在现实世界中,访问者又叫做拜访者。客人到主人家做客,客人就是一个拜访者。对主人来说,你来与不来,我都在那里。
什么是访问者模式
访问者是一种行为型模式,主要是对象自身的结构和对象的具体行为相分离,通过一个对象维护对象自身的结构(这个结构不能是易变的,否则这种模式就没太大的意义了),通过另一个对象(就是我们说的访问者)维护施加在对象结构上的行为。
通过将对象的结构和行为进行相分离,可以让对象的行为独立变化,当需要增加新的行为时,只需要改变访问者即可,而对象的结构是不需要变化的。
基本结构
Node表示对象结构的抽象定义;
Visitor表示访问者,即对象的行为定义在此对象内;
DataStructure表示有多个对象组成的数据结构对象,相当于对象的容器;
使用场景
- 对象的结构是不易变的,但是对象的行为是易变的,此时就可以将对象的结构和行为进行解耦操作;
优点
- 好的扩展性
- 好的复用性
- 分离无关行为
缺点
- 对象结构变化很困难
- 破坏了封装性
使用案例
Demo
import java.util.ArrayList;
import java.util.List;
/**
*
* 访问者模式:行为型模式
*
* 基本构件:
* (1)抽象访问者:声明访问者可以访问哪些元素
* (2)具体访问者:实现抽象访问者中声明的方法
* (3)抽象元素类:声明接收哪一类访问者访问;同时还包含自己的一些业务逻辑
* (4)具体元素类:实现抽象元素类所声明的accept方法
* (5)结构对象:一个元素的容器
*
* 适用场景:防止一些不相干的操作干扰元素本身,可以将这些不相干的操作提到访问者中。
* 如果一个对象结构非常复杂,同时结构不易变化,但需要经常定义基于此结构上的新操作,则
* 非常适用于访问者模式。比如:复杂的集合对象、XML文档解析、编译器的设计等。
*
* 注:核心是结构不易变,而定义在上的操作易变;
* 行为是在访问者中实现的,元素中主要是保存结构信息。
*
* 比如一份静态数据,相当于结构不易变的,但是呢,经常需要变换指标来衡量一个标准,则可以
* 采用访问者模式
*
*
*/
public class VisitorBase {
public static void main(String[] args) {
Element element = new Student("s1", 91, 3);
Element element1 = new Student("s2", 98, 3);
Element element2 = new Teacher("t1", 101, 10);
Element element3 = new Teacher("t2", 103, 20);
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.addElement(element)
.addElement(element1).addElement(element2).addElement(element3);
ReseacrcherVisitor visitor = new ReseacrcherVisitor();
objectStructure.accept(visitor);
System.out.println("select another");
ScoreVisitor visitor1 = new ScoreVisitor();
objectStructure.accept(visitor1);
}
static class ObjectStructure {
List<Element> elements = new ArrayList<>();
public void accept(IVisitor visitor) {
for(Element element : elements) {
element.accept(visitor);
}
}
public ObjectStructure addElement(Element element) {
elements.add(element);
return this;
}
public ObjectStructure removeElement(Element element) {
elements.remove(element);
return this;
}
}
static interface IVisitor {
void visit(Teacher teacher);
void visit(Student student);
}
static class ReseacrcherVisitor implements IVisitor {
@Override
public void visit(Teacher teacher) {
if(teacher.paperCount > 6) {
System.out.println("老师论文数达到了6篇,入选优秀工作者");
}
}
@Override
public void visit(Student student) {
if(student.paperCount > 2) {
System.out.println("学生论文数达到了2篇,入选优秀工作者");
}
}
}
static class ScoreVisitor implements IVisitor {
@Override
public void visit(Teacher teacher) {
if(teacher.score > 100) {
System.out.println("老师分数达到了100,入选优秀工作者");
}
}
@Override
public void visit(Student student) {
if(student.score > 90) {
System.out.println("学生分数达到了90,入选优秀工作者");
}
}
}
static interface Element {
void accept(IVisitor visitor);
}
static class Teacher implements Element {
private String name;
private int score;
private int paperCount;
public Teacher(String name, int score, int paperCount) {
this.name = name;
this.score = score;
this.paperCount = paperCount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getPaperCount() {
return paperCount;
}
public void setPaperCount(int paperCount) {
this.paperCount = paperCount;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
static class Student implements Element {
private String name;
private int score;
private int paperCount;
public Student(String name, int score, int paperCount) {
this.name = name;
this.score = score;
this.paperCount = paperCount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getPaperCount() {
return paperCount;
}
public void setPaperCount(int paperCount) {
this.paperCount = paperCount;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
}
Spring的案例
public abstract class AnnotationVisitor {
}
public abstract class ClassVisitor {
}
public abstract class FieldVisitor {
}
public abstract class MethodVisitor {
}
public abstract class ModuleVisitor {
}
大家搜索spring源码会发现这些抽象类,用于访问注解、类、成员变量等。在Visitor中定义操作这些对象的一些操作。