模式动机
对于存储在一个集合中的对象,他们可能具有不同的类型(即使有一个公共的接口),对于该集合中的对象,可以接受一类称为访问者的对象来访问,不同的访问者其访问方式也有所不同。
定义
表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
结构图
基本代码
package visitor;
public interface Visitor {
void visitConcreteElementA(ConcreteElementA concreteElementA);
void visitConcreteElementB(ConcreteElementB concreteElementB);
}
package visitor;
public interface Element {
void accept(Visitor visitor);
}
package visitor;
public class ConcreteElementA implements Element{
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
package visitor;
public class ConcreteElementB implements Element {
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
package visitor;
public class ConcreteVisitor1 implements Visitor{
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
}
package visitor;
public class ConcreteVisitor2 implements Visitor{
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
}
package visitor;
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure {
private List<Element> elements = new ArrayList<Element>();
public void attach(Element element){
elements.add(element);
}
public void detach(Element element){
elements.remove(element);
}
public void accept(Visitor visitor){
for (Element element:elements){
element.accept(visitor);
}
}
}
package visitor;
public class Client {
public static void main(String[] args) {
ObjectStructure o = new ObjectStructure();
o.attach(new ConcreteElementA());
o.attach(new ConcreteElementB());
ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
ConcreteVisitor2 visitor2 = new ConcreteVisitor2();
o.accept(visitor1);
o.accept(visitor2);
}
}
开发中的场景
- XML文档解析器设计
- 编译器的设计
- 复杂集合对象的处理
小结
访问者模式适用于数据结构相对稳定的系统。它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
目的
访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统数据结构相对易于变化,经常要有新的数据对象增加进来,就不适合使用访问者模式。
优点
增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
缺点
使增加新的数据结构变得困难。