模式動(dòng)機(jī)
對(duì)于存儲(chǔ)在一個(gè)集合中的對(duì)象,他們可能具有不同的類(lèi)型(即使有一個(gè)公共的接口),對(duì)于該集合中的對(duì)象,可以接受一類(lèi)稱(chēng)為訪問(wèn)者的對(duì)象來(lái)訪問(wèn),不同的訪問(wèn)者其訪問(wèn)方式也有所不同瘾婿。
定義
表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作,它使我們可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作烤咧。
結(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()+"訪問(wèn)");
}
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"訪問(wèn)");
}
}
package visitor;
public class ConcreteVisitor2 implements Visitor{
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"訪問(wèn)");
}
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"訪問(wèn)");
}
}
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);
}
}
開(kāi)發(fā)中的場(chǎng)景
- XML文檔解析器設(shè)計(jì)
- 編譯器的設(shè)計(jì)
- 復(fù)雜集合對(duì)象的處理
小結(jié)
訪問(wèn)者模式適用于數(shù)據(jù)結(jié)構(gòu)相對(duì)穩(wěn)定的系統(tǒng)偏陪。它把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作之間的耦合解脫開(kāi),使得操作集合可以相對(duì)自由地演化髓削。
目的
訪問(wèn)者模式的目的是要把處理從數(shù)據(jù)結(jié)構(gòu)分離出來(lái)竹挡。很多系統(tǒng)可以按照算法和數(shù)據(jù)結(jié)構(gòu)分開(kāi),如果這樣的系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu)立膛,又有易于變化的算法的話揪罕,使用訪問(wèn)者模式就是比較合適的,因?yàn)樵L問(wèn)者模式使得算法操作的增加變得容易宝泵。反之好啰,如果這樣的系統(tǒng)數(shù)據(jù)結(jié)構(gòu)相對(duì)易于變化,經(jīng)常要有新的數(shù)據(jù)對(duì)象增加進(jìn)來(lái)儿奶,就不適合使用訪問(wèn)者模式框往。
優(yōu)點(diǎn)
增加新的操作很容易,因?yàn)樵黾有碌牟僮骶鸵馕吨黾右粋€(gè)新的訪問(wèn)者闯捎。訪問(wèn)者模式將有關(guān)的行為集中到一個(gè)訪問(wèn)者對(duì)象中椰弊。
缺點(diǎn)
使增加新的數(shù)據(jù)結(jié)構(gòu)變得困難许溅。