一、概述
1、定义
Represent an operation to be performed on the elements of an object structure.Visitor lets you define a new operation without changing the classes of the elements on which it operates.(封装一些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作)。
2、通用类图
3、基本介绍
- 访问者模式是用于封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作;
- 主要是将数据结构与数据操作分离,解决数据结构和操作耦合性问题;
- 访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口;
二、通用源码
元素角色:
声明接受哪一类访问者访问,通过accept方法实现。
//抽象元素
public abstract class Element {
//定义业务逻辑
public abstract void doSomething();
//允许谁来访问
public abstract void accept(Visitor visitor);
}
//具体的元素
public class ConcreteElement extends Element {
@Override
public void doSomething() {
//业务逻辑处理
}
//允许哪个访问者访问
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
访问者角色:
声明访问者可以访问哪些元素,通过visit实现。
//抽象访问者
public interface Visitor {
//定义可以访问的对象
public void visit(ConcreteElement element);
}
//具体的访问者
public class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElement element) {
//访问元素,并做出处理
element.doSomething();
}
}
结构对象:
元素产生者,一般容纳在多个不同类、不同接口的容器,如List、Set、Map等。
public class ObjectStructure {
//对象集合
private List<Element> elements=new LinkedList<>();
//添加元素
public void add(Element element){
elements.add(element);
}
//移除元素
public void remove(Element element){
elements.remove(element);
}
//访问元素
public void display(Visitor visitor){
for (Element element:elements){
element.accept(visitor);
}
}
}
Client端调用:
public class Main {
public static void main(String[] args){
//创建一个ObjectStructure
ObjectStructure objectStructure=new ObjectStructure();
objectStructure.add(new ConcreteElement());
//创建一个访问者
Visitor visitor=new ConcreteVisitor();
//访问元素
objectStructure.display(visitor);
}
}
三、访问者模式的应用
1、优点
- 符合单一职责原则:元素负责数据的加载,访问者负责数据的展现,职责明确;
- 优秀的扩展性:由于职责分开相互独立,所以要添加访问者和元素相当方便;
2、缺点
- 具体元素对访问者公布细节,访问者要访问的元素必然会造成元素的数据与方法暴露,违背了迪米特法则;
- 违背了依赖倒置原则:访问者依赖的是具体的角色,而不是抽象角色;
3、使用场景
- 一个对象结构类包含很多类对象,它们有很多不同的接口,而你相对这些对象实施一些依赖于其具体类的操作,也就是说使用迭代器模式已经不能胜任的场景;
- 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象的类;
- 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统;
- 如果一个系统有稳定的数据结构,又有经常变化的功能需求,那么访问者模式是比较适合的。