1.把数据结构与相关的处理分离开,另外写一个表示在数据结构内穿梭来去的主体“访客”的类,然后把处理交给这个类来进行。如此一来,如果想追加新的处理行为时,只要再建立一个新的“访客”即可。而在数据结构这边,也只要能接受来敲门的“访客”就能完成动作。
2.示例:
package com.cn.amk;
import java.util.Iterator;
import java.util.Vector;
abstract class Visitor {
public abstract void visit(File file);
public abstract void visit(Directory directory);
}
class ListVisitor extends Visitor{
private String currentDir = "";
public void visit(File file) {
System.out.println(currentDir + "/" + file);
}
public void visit(Directory directory) {
System.out.println(currentDir + "/" + directory);
String saveDir = currentDir;
currentDir = currentDir + "/" + directory.getName();
Iterator<Entry> it = directory.iterator();
while (it.hasNext()) {
Entry entry = (Entry)it.next();
System.out.println(this.currentDir + " hehe");
entry.accept(this);
}
currentDir = saveDir;
}
}
interface Acceptor {
public void accept(Visitor v);
}
abstract class Entry implements Acceptor{
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry) throws FileTreatmentException {
throw new FileTreatmentException();
}
public Iterator<Entry> iterator() throws FileTreatmentException {
throw new FileTreatmentException();
}
public String toString() {
return getName() + "<" + getSize() + ">";
}
}
class File extends Entry {
String name;
int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
public void accept(Visitor v){
v.visit(this);
};
}
class Directory extends Entry {
private String name;
private Vector<Entry> directory = new Vector<Entry>();
public Directory(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getSize() {
int size = 0;
Iterator<Entry> it = directory.iterator();
while(it.hasNext()) {
Entry entry = (Entry)it.next();
size += entry.getSize();
}
return size;
}
public Iterator<Entry> iterator() {
return directory.iterator();
}
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
public void accept(Visitor v){
v.visit(this);
}
}
class FileTreatmentException extends RuntimeException {
private static final long serialVersionUID = 1L;
public FileTreatmentException() {
}
public FileTreatmentException(String msg) {
super(msg);
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Making root entries...");
Directory rootdir = new Directory("root");
Directory bindir = new Directory("bin");
Directory tmpdir = new Directory("tmp");
Directory usrdir = new Directory("usr");
rootdir.add(bindir);
rootdir.add(tmpdir);
rootdir.add(usrdir);
bindir.add(new File("vi",10000));
bindir.add(new File("latex",20000));
rootdir.accept(new ListVisitor());
}
}
这一示例的数据结构是文件层次结构。visitor提供对其层次的一个遍历行为。
3.另外一个例子:
package com.cn.dai;
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
A a3 = new A(3);
A a4 = new A(4);
A a5 = new A(5);
A a6 = new A(6);
A a7 = new A(7);
a5.setArrayList(a6);
a5.setArrayList(a7);
a1.setArrayList(a2);
a1.setArrayList(a3);
a3.setArrayList(a4);
a3.setArrayList(a5);
a1.accept(new ListVisit());
}
}
abstract class Visitor {
public abstract void visit(Entry entry);
}
class ListVisit extends Visitor{
private int total;
@Override
public void visit(Entry entry) {
total += entry.getN();
System.out.println(entry.getN());
System.out.println("total: " + total);
Iterator<Entry> it = entry.iterator();
while(it.hasNext()) {
Entry en = (Entry)it.next();
en.accept(this);
}
System.out.println("endtotal: " + total);
}
}
interface Acceptor {
public abstract void accept(Visitor v);
}
abstract class Entry implements Acceptor {
public abstract void accept(Visitor v);
public abstract int getN();
public abstract void setArrayList(Entry n);
public abstract Iterator<Entry> iterator();
}
class A extends Entry{
private int n;
private ArrayList<Entry> al = new ArrayList<Entry>();
public A(int n) {
this.n = n;
}
public A(int n,A a) {
this.n = n;
this.al.add(a);
}
public int getN() {
return n;
}
public void setArrayList(Entry n) {
al.add(n);
}
public void accept(Visitor v) {
v.visit(this);
}
@Override
public Iterator<Entry> iterator() {
return al.iterator();
}
}
这一例子的数据结构是一个用ArrayList构建的树,每个节点有其值。visitor的操作时遍历整个数,求整个数的数值和。
4.为什么要搞得这么复杂:
visitor pattern的目的是要把处理从数据结构分出来。在集合元素或元素间的连结时,数据结构的地位非常重要。但是维持这个结构跟写一个以这个机构为基础的处理完全是两回事。