模式動(dòng)機(jī)
對于存儲(chǔ)在一個(gè)集合中的對象,他們可能具有不同的類型(即使有一個(gè)公共的接口),對于該集合中的對象,可以接受一類稱為訪問者的對象來訪問,不同的訪問者其訪問方式也有所不同。
定義
表示一個(gè)作用于某對象結(jié)構(gòu)中的各元素的操作,它使我們可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
結(jié)構(gòu)圖

訪問者模式
基本代碼
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);
}
}
開發(fā)中的場景
- XML文檔解析器設(shè)計(jì)
- 編譯器的設(shè)計(jì)
- 復(fù)雜集合對象的處理
小結(jié)
訪問者模式適用于數(shù)據(jù)結(jié)構(gòu)相對穩(wěn)定的系統(tǒng)。它把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。
目的
訪問者模式的目的是要把處理從數(shù)據(jù)結(jié)構(gòu)分離出來。很多系統(tǒng)可以按照算法和數(shù)據(jù)結(jié)構(gòu)分開,如果這樣的系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),又有易于變化的算法的話,使用訪問者模式就是比較合適的,因?yàn)樵L問者模式使得算法操作的增加變得容易。反之,如果這樣的系統(tǒng)數(shù)據(jù)結(jié)構(gòu)相對易于變化,經(jīng)常要有新的數(shù)據(jù)對象增加進(jìn)來,就不適合使用訪問者模式。
優(yōu)點(diǎn)
增加新的操作很容易,因?yàn)樵黾有碌牟僮骶鸵馕吨黾右粋€(gè)新的訪問者。訪問者模式將有關(guān)的行為集中到一個(gè)訪問者對象中。
缺點(diǎn)
使增加新的數(shù)據(jù)結(jié)構(gòu)變得困難。