訪問者模式(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中定義操作這些對象的一些操作。