定义
提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。
UML类图
代码实现
Element.java
public interface Element {
public void accept(Visitor visitor);
}
Visitor.java
public abstract class Visitor {
public abstract void visit(ConcreteElementA elementA);
public abstract void visit(ConcreteElementB elementB);
}
ConcreteElementA.java
public class ConcreteElementA implements Element {
private String name;
public ConcreteElementA(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
ConcreteElementB.java
public class ConcreteElementB implements Element {
private int value;
public ConcreteElementB(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
ConcreteVisitorA.java
public class ConcreteVisitorA extends Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("ConcreteVisitorA visit ConcreteElementA name:"+elementA.getName());
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("ConcreteVisitorA visit ConcreteElementB value:"+elementB.getValue());
}
}
ConcreteVisitorB.java
public class ConcreteVisitorB extends Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("ConcreteVisitorB visit ConcreteElementA name:"+elementA.getName());
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("ConcreteVisitorB visit ConcreteElementB value:"+elementB.getValue());
}
}
ObjectStructure.java
public class ObjectStructure {
private ArrayList<Element> list = new ArrayList<>();
public void accept(Visitor visitor) {
for (Element element:list) {
element.accept(visitor);
}
}
public void add(Element element) {
list.add(element);
}
public void remove(Element element) {
list.remove(element);
}
}
Main.java
ObjectStructure objectStructure = new ObjectStructure();
Element element1 = new ConcreteElementA("zhangsan");
Element element2 = new ConcreteElementA("lisi");
Element element3 = new ConcreteElementA("wangwu");
Element element4 = new ConcreteElementB(1);
Element element5 = new ConcreteElementB(4);
Element element6 = new ConcreteElementB(7);
objectStructure.add(element1);
objectStructure.add(element2);
objectStructure.add(element3);
objectStructure.add(element4);
objectStructure.add(element5);
objectStructure.add(element6);
Visitor visitorA = new ConcreteVisitorA();
objectStructure.accept(visitorA);
System.out.println("---------------------------------");
Visitor visitorB = new ConcreteVisitorB();
objectStructure.accept(visitorB);
打印的结果:
ConcreteVisitorA visit ConcreteElementA name:zhangsan
ConcreteVisitorA visit ConcreteElementA name:lisi
ConcreteVisitorA visit ConcreteElementA name:wangwu
ConcreteVisitorA visit ConcreteElementB value:1
ConcreteVisitorA visit ConcreteElementB value:4
ConcreteVisitorA visit ConcreteElementB value:7
---------------------------------
ConcreteVisitorB visit ConcreteElementA name:zhangsan
ConcreteVisitorB visit ConcreteElementA name:lisi
ConcreteVisitorB visit ConcreteElementA name:wangwu
ConcreteVisitorB visit ConcreteElementB value:1
ConcreteVisitorB visit ConcreteElementB value:4
ConcreteVisitorB visit ConcreteElementB value:7
优缺点
主要优点
-
增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
-
将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
-
让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。
主要缺点
-
增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
-
破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。