定義
提供一個作用於某對象結構中的各元素的操作表示,它使我們可以在不改變各元素的類的前提下定義作用於這些元素的新操作。訪問者模式是一種對象行爲型模式。
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
優缺點
主要優點
-
增加新的訪問操作很方便。使用訪問者模式,增加新的訪問操作就意味着增加一個新的具體訪問者類,實現簡單,無須修改源代碼,符合“開閉原則”。
-
將有關元素對象的訪問行爲集中到一個訪問者對象中,而不是分散在一個個的元素類中。類的職責更加清晰,有利於對象結構中元素對象的複用,相同的對象結構可以供多個不同的訪問者訪問。
-
讓用戶能夠在不修改現有元素類層次結構的情況下,定義作用於該層次結構的操作。
主要缺點
-
增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類都意味着要在抽象訪問者角色中增加一個新的抽象操作,並在每一個具體訪問者類中增加相應的具體操作,這違背了“開閉原則”的要求。
-
破壞封裝。訪問者模式要求訪問者對象訪問並調用每一個元素對象的操作,這意味着元素對象有時候必須暴露一些自己的內部操作和內部狀態,否則無法供訪問者訪問。