简介
封装作用于某数据结构中的各元素的操作,可以在不改变各元素类的前提下,定义作用于这些元素的操作,将算法与数据结构进行分离,本质上,访问者允许在不修改类的情况下向类添加新的虚拟函数。属于行为型。
适用场景
1、一个数据结构(List/Map等)包含很多类型对象
2、数据结构与数据操作分离
3、需要对对象结构进行许多不相关的操作
4、组成对象结构的类是已知的,并且不会改变
5、需要经常添加新操作
6、算法涉及对象结构的多个类,但是需要在一个位置管理它
7、算法需要跨越几个独立的类层次结构
优点
1、增加新的操作很容易,即增加一个新的访问者就可以了
2、符合开闭原则
缺点
1、增加新的数据结构比较困难
2、具体元素变更比较麻烦
代码示例
汽车元素
public interface CarElement {
void accept(CarElementVisitor visitor);
}
汽车元素访问者
public interface CarElementVisitor {
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
车身
public class Body implements CarElement{
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
车轮
public class Wheel implements CarElement {
private final String name;
public Wheel(final String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
引擎
public class Engine implements CarElement{
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
汽车
public class Car implements CarElement{
private List<CarElement> elements;
public Car() {
this.elements = new ArrayList<>();
this.elements.add(new Wheel("前左"));
this.elements.add(new Wheel("前右"));
this.elements.add(new Wheel("后左"));
this.elements.add(new Wheel("后右"));
this.elements.add(new Body());
this.elements.add(new Engine());
}
@Override
public void accept(CarElementVisitor visitor) {
for (CarElement element : elements) {
element.accept(visitor);
}
visitor.visit(this);
}
}
启动汽车访问者
public class CarElementDoVisitor implements CarElementVisitor{
@Override
public void visit(Body body) {
System.out.println("移动车身");
}
@Override
public void visit(Car car) {
System.out.println("启动车子");
}
@Override
public void visit(Wheel wheel) {
System.out.println("启动我的 " + wheel.getName() + " 车轮");
}
@Override
public void visit(Engine engine) {
System.out.println("开启引擎");
}
}
打印汽车访问者
public class CarElementPrintVisitor implements CarElementVisitor{
@Override
public void visit(Body body) {
System.out.println("访问车身");
}
@Override
public void visit(Car car) {
System.out.println("访问汽车");
}
@Override
public void visit(Engine engine) {
System.out.println("访问引擎");
}
@Override
public void visit(Wheel wheel) {
System.out.println("访问 " + wheel.getName() + " 车轮");
}
}
测试类
public class VisitorTest {
public static void main(String[] args) {
Car car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
}
输出结果为:
访问 前左 车轮
访问 前右 车轮
访问 后左 车轮
访问 后右 车轮
访问车身
访问引擎
访问汽车
启动我的 前左 车轮
启动我的 前右 车轮
启动我的 后左 车轮
启动我的 后右 车轮
移动车身
开启引擎
启动车子
源码分析
jdk中应用
FileVisitor
从名字可以看出是一个访问者,可以遍历文件的一些属性。
spring中应用
BeanDefinitionVisitor
可以遍历一些bean的属性
本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点
注意:本文归作者所有,未经作者允许,不得转载