访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式适用于数据结构相对稳定的系统。
它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
访问者模式的目的是要把处理从数据结构分离出来。
有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。
访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
访问者的缺点就是使增加新的数据结构变得困难了。
大多数时候并不需要用访问者模式,但当一旦需要访问者模式时,那就是真的需要它了。
访问者模式基本代码:
Visitor类,为该对象结构中ConcreteElement的每一个类声明一个Visit操作。
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
ConcreteVisitor1和ConcreteVisitor2类,具体访问者,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法片段乃是对应于结构中对象的类。
public class ConcreteVisitor1 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "访问");
}
}
Element类,定义一个Accept操作,它以一个访问者为参数。
public abstract class Element {
public abstract void accept(Visitor visitor);
}
ConcreteElementA和ConcreteElementB类,具体元素,实现accept操作。
public class ConcreteElementA extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void operationA() {
// 其他相关方法
}
}
public class ConcreteElementB extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
public void operationB() {
// 其他相关方法
}
}
ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。
public class ObjectStructure {
private List<Element> mElements = new ArrayList<Element>();
public void attach(Element element) {
mElements.add(element);
}
public void detach(Element element) {
mElements.remove(element);
}
public void accept(Visitor visitor) {
for (Element item : mElements) {
item.accept(visitor);
}
}
}
调用:
ObjectStructure structure = new ObjectStructure();
structure.attach(new ConcreteElementA());
structure.attach(new ConcreteElementB());
ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
structure.accept(visitor1);
输出结果:
ConcreteElementA被ConcreteVisitor1访问
ConcreteElementB被ConcreteVisitor1访问
例子: