定义
封装作用于某数据结构(如List/Set/Map等)中的各元素的操作。
可以在不改变各元素的类的前提下,定义作用于这些元素的操作。
类型
行为型
适用场景
①、一个数据结构如(List/Set/Map等)包含很多类型对象。
②、数据结构与数据操作分离。
优缺点
优点:
①、增加新的操作很容易,即增加一个新的访问者。
缺点:
①、增加新的数据结构困难。
②、具体元素变更比较麻烦。
代码实现
案例:现在有很多学习平台都提供了学习课程。当然有免费的,还有收费的。收费的,你可以看到价格,而免费的,就没有价格。
定一个课程类
public abstract class Course {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void accept(Visitor visitor);
}
accept()接收一个访问者。
先创建免费课程
public class FreeCourse extends Course {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
再创建收费课程
public class CodingCourse extends Course {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
创建一个访问者
public interface Visitor {
void visit(FreeCourse freeCourse);
void visit(CodingCourse codingCourse);
}
编写它的实现类
public class VisitorImpl implements Visitor {
/**
* 访问免费课程,打印所有免费课程的名称
*/
@Override
public void visit(FreeCourse freeCourse) {
System.out.println("免费课程:" + freeCourse.getName());
}
/**
* 访问实战课程,打印所有实战课程的名称和价格
*/
@Override
public void visit(CodingCourse codingCourse) {
System.out.println("实战课程:" + codingCourse.getName() + ",价格:" + codingCourse.getPrice());
}
}
编写测试类
public class MainTest {
public static void main(String[] args) {
List<Course> courseList = new ArrayList<>();
FreeCourse freeCourse = new FreeCourse();
freeCourse.setName("三小时学会SpringBoot");
CodingCourse codingCourse = new CodingCourse();
codingCourse.setName("Mybatis Plus实现自动消息回复");
codingCourse.setPrice(99.9D);
courseList.add(freeCourse);
courseList.add(codingCourse);
courseList.forEach((course) -> course.accept(new VisitorImpl()));
}
}
查看输出结果
C:\android\java\jdk1.8\bin\java.exe
免费课程:三小时学会SpringBoot
实战课程:Mybatis Plus实现自动消息回复,价格:99.9
如果在平时的开发过程中遇到数据加载或者数据分离的情况下,就可以考虑访问者模式。
相关源码
1. Jdk中的FileVisitor类。
2. Spring中的BeanDefinitionVisitor。