Separate data structure and processing. Prepare a class that represents the visitors who roam the data structure, and let that class handle the processing. The data structure side will accept visitors.
The Visitor role is said to have "visited xxx" for each specific element of the data structure (ConcreteElement role). Declare the visit (xxx) method. visit (xxx) is a method for processing xxx, and the actual code is written on the side of the Concrete Visit role.
package visitor;
public abstract class Visitor {
public abstract void visit(File file);
public abstract void visit(Directory directory);
}
The ConcreteVisitor role implements the Visitor role interface. Implement a method in the form of visit (xxx) and describe the processing for each ConcreteElement role.
package visitor;
import java.util.Iterator;
public class ListVisitor extends Visitor{
private String currentDir = "";
@Override
public void visit(File file) {
System.out.println(currentDir + "/" + file);
}
public void visit(Directory directory) {
System.out.println(currentDir + "/" + directory);
String savedDir = currentDir;
currentDir = currentDir + "/" + directory.getName();
Iterator<Entry> it = directory.iterator();
while (it.hasNext()) {
Entry entry = it.next();
entry.accept(this);
}
currentDir = savedDir;
}
}
The role of Element is a role that represents the destination of the role of Visitor. Declare an accept method that accepts visitors. The Visitor role is passed to the argument of the accept method.
package visitor;
public interface Element {
public abstract void accept(Visitor v);
}
The ConcreteElement role is the role that implements the interface of the Element role.
package visitor;
public class File extends Entry{
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
package visitor;
import java.util.ArrayList;
import java.util.Iterator;
public class Directory extends Entry{
private String name;
private ArrayList<Entry> directory = new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
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 Entry add(Entry entry) {
directory.add(entry);
return this;
}
public Iterator<Entry> iterator() {
return directory.iterator();
}
public void accept(Visitor v) {
v.visit(this);
}
}
The Object Structure role is a role that handles a set of Element roles. It has a method that allows the ConcreteVisitor role to handle individual Element roles. This role corresponds to the above Directory class.
package visitor;
public class Main {
public static void main(String[] args) {
try {
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());
System.out.println();
System.out.println("Making user entryies...");
Directory yuki = new Directory("yuki");
Directory hanako = new Directory("hanako");
Directory tomura = new Directory("tomura");
usrDir.add(yuki);
usrDir.add(hanako);
usrDir.add(tomura);
yuki.add(new File("diary.html", 100));
yuki.add(new File("Composite.java", 200));
hanako.add(new File("memo.tex", 300));
tomura.add(new File("game.doc", 400));
tomura.add(new File("junk.mail", 500));
rootDir.accept(new ListVisitor());
} catch (FileThreatmentException e) {
e.printStackTrace();
}
}
}
https://github.com/aki0207/visitor
I used this as a reference. Augmented and Revised Introduction to Design Patterns Learned in Java Language
Recommended Posts