该项目源码地址:https://github.com/ggb2312/JavaNotes/tree/master/design-pattern(设计模式相关代码与笔记)
1. 定义
封装作用于某数据结构(如List/Set/Map等)中的各元素的操作(可以在不改变各元素的类的前提下,定义作用于这些元素的操作)
2. 适用场景
- 一个数据结构如(List/Set/Map等)包含很多类型对象
- 数据结构与数据操作分离
3. 类图以及角色
Visitor:接口或者抽象类,它定义了对每一个元素(Element)访问的行为,它的参数就是可以访问的元素,它的方法数理论上来讲与元素个数是一样的,因此,访问者模式要求元素的类族要稳定,如果经常添加、移除元素类,必然会导致频繁地修改Visitor接口,如果这样则不适合使用访问者模式。
ConcreteVisitorA、ConcreteVisitorB :具体的访问类,它需要给出对每一个元素类访问时所产生的具体行为。
Element:元素接口或者抽象类,它定义了一个接受访问者的方法(Accept),其意义是指每一个元素都要可以被访问者访问。
ConcreteElementA、ConcreteElementB:具体的元素类,它提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
ObjectStructure:定义当中所说的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素供访问者访问。
3. 相关设计模式
访问者模式和迭代器模式
- 相同点:都是在某种数据结构上面处理
- 不同点:访问者模式用于对保存在数据结构的元素进行某种特定的处理,迭代器模式重要用于逐个遍历在数据结构中的元素。
4. 模式实例
背景:不同的访问者(普通用户、老板)查看不同的课程(免费课程、收费课程),可以看到不同的结果。
(1)Visitor 访问者接口
/**
* Create by eval on 2019/2/11
*/
public interface IVisitor {
void visit(FreeCourse freeCourse);
void visit(CodingCourse codingCourse);
}
(2)ConcreteVisitor 访问者实现类
/**
* Create by eval on 2019/2/11
*/
public class Visitor implements IVisitor {
/**
* 访问免费课程,打印所有免费课程名称
*
* @param freeCourse
*/
@Override
public void visit(FreeCourse freeCourse) {
System.out.println("免费课程:" + freeCourse.getName());
}
/**
* 访问实战课程,打印所有实战课程名称以及价格
*
* @param codingCourse
*/
@Override
public void visit(CodingCourse codingCourse) {
System.out.println("实战课程:" + codingCourse.getName() + " 价格:" + codingCourse.getPrice()+ "元");
}
}
(3)Element 课程接口
/**
* Create by eval on 2019/2/11
*/
public abstract class Course {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void accept(IVisitor visitor);
}
(4)ConcreteElement 课程实现类
/**
* Create by eval on 2019/2/11
*/
public class CodingCourse extends Course {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* Create by eval on 2019/2/11
*/
public class FreeCourse extends Course {
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
(5)测试
import java.util.ArrayList;
import java.util.List;
/**
* Create by eval on 2019/2/11
*/
public class Test {
public static void main(String[] args) {
List courseList = new ArrayList<>();
FreeCourse freeCourse = new FreeCourse();
freeCourse.setName("SpringMVC数据绑定");
CodingCourse codingCourse = new CodingCourse();
codingCourse.setName("Java设计模式");
codingCourse.setPrice(299);
courseList.add(freeCourse);
courseList.add(codingCourse);
for (Course course : courseList) {
course.accept(new Visitor());
}
}
}
测试结果:
5. 优缺点
优点:
- 增加新的操作很容易,即增加一个新的访问者
缺点:
- 增加新的数据结构困难
- 具体元素变更比较麻烦
6. 扩展-JDK1.7源码以及框架中的访问者模式
java.nio.file.FileVisitor以及实现类SimpleFileVisitor
org.springframework.beans.factory.config.BeanDefinitionVisitor可以遍历Bean的各种属性,委托valueResolver来实现
参考
https://www.cnblogs.com/chenssy/p/3339756.html