Visitor模式
数据结构与处理被分离开来,其类图如下
登场的角色:
-
Visitor(访问者)
访问者接口,声明了visit接口 -
ConcreteVisitor(具体的访问者)
Visitor的具体实现 -
Element(元素)
Element角色表示Visitor角色的访问对象 -
ConcreteElement
实现Element角色所定义的接口 -
ObjectStructure(对象结构)
ObjectStructure负责处理Element角色的集合。
Visitor模式的一个实例
下面是各个类的说明
名字 | 说明 |
---|---|
Visitor | 表示访问者的抽象类 |
Element | 表示元素类的接口 |
ListVisitor | Visitor的实现类 |
Entry | 实现了 Element接口 |
File | 表示文件的类 |
Directory | 表示文件夹的类 |
FileTreatmentException | 新建的异常类 |
Mian | 测试类 |
uml类图(只含继承,实现关系)
uml类图
Visitor类
package xin.ajay.visitor;
public abstract class Visitor {
public abstract void visit(File file);
public abstract void visit(Directory directory);
}
Element接口
package xin.ajay.visitor;
public interface Element {
public abstract void accept(Visitor v);
}
ListVisitor类
package xin.ajay.visitor;
import java.util.Iterator;
public class ListVisitor extends Visitor {
private String currentdir="";
@Override
public void visit(File file) {
System.out.println(currentdir + "/" +file);
}
@Override
public void visit(Directory directory) {
System.out.println(currentdir + "/" +directory);
String savedir = currentdir;
currentdir = currentdir + "/" + directory.getName();
Iterator<Entry> iterator = directory.iterator();
while (iterator.hasNext()){
Entry entry = (Entry) iterator.next();
entry.accept(this);
}
currentdir =savedir;
}
}
Entry类
package xin.ajay.visitor;
import java.util.Iterator;
public abstract class Entry implements Element{
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry) throws FileTreatmentException {
throw new FileTreatmentException();
}
public Iterator iterator() throws FileTreatmentException{
throw new FileTreatmentException();
}
public String toString(){
return getName() + " (" +getSize() + ")";
}
}
File类
package xin.ajay.visitor;
public class File extends Entry {
private String name;
private int size;
public File(String name,int size){
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
Directory类
package xin.ajay.visitor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Directory extends Entry {
private String name;
private List<Entry> dir = new ArrayList<>();
public Directory(String name) {
this.name = name;
}
public String getName(){
return name;
}
public int getSize(){
int size = 0;
Iterator<Entry> iterator = dir.iterator();
while (iterator.hasNext()){
Entry entry = (Entry)iterator.next();
size += entry.getSize();
}
return size;
}
public Entry add(Entry entry){
dir.add(entry);
return this;
}
public Iterator<Entry> iterator(){
return dir.iterator();
}
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
FileTreatmentException类
package xin.ajay.visitor;
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException(){
}
public FileTreatmentException(String msg){
super(msg);
}
}
Main
package xin.ajay.visitor;
public class Main {
public static void main(String[] args) {
/*
--|root
----|bin
------|vi
------|latex
----|tmp
----|usr
-------------------------------------------
--|root
----|bin
------|vi
------|latex
----|tmp
----|usr
------|yuki
--------|diary.html
--------|Composite.java
------|hanako
--------|memo.tex
------|tomura
--------|game.doc
--------|iunk.mail
*/
System.out.println("Making root entries...");
Directory root = new Directory("root");
Directory bin = new Directory("bin");
Directory tmp = new Directory("tmp");
Directory usr = new Directory("usr");
root.add(bin);
root.add(tmp);
root.add(usr);
bin.add(new File("vi",100));
bin.add(new File("latex",200));
//访问者
root.accept(new ListVisitor());
System.out.println();
System.out.println("Making user entries...");
Directory yuki = new Directory("yuki");
yuki.add(new File("diary.html", 10));
yuki.add(new File("Composite.java",20));
Directory hanako = new Directory("hanako");
hanako.add(new File("memo.tex",11));
Directory tomura = new Directory("tomura");
tomura.add(new File("game.doc",12));
tomura.add(new File("iunl.mail",13));
usr.add(yuki);
usr.add(hanako);
usr.add(tomura);
root.accept(new ListVisitor());
}
}