Visitorパターン
v.visit(this)が新鮮。されど再帰を絡めた例にする必要はあったのだろうかと。
% find . -name "*.java" -print0 |xargs -0 cat [] import java.util.ArrayList; import java.util.Iterator; public class Directory extends Entry { private String name; private ArrayList<Entry> dir = new ArrayList<Entry>(); public Directory(String name) { this.name = name; } @Override public void accept(Visitor v) { v.visit(this); } @Override public String getName() { return name; } @Override public int getSize() { int size = 0; Iterator<Entry> it = dir.iterator(); while (it.hasNext()) { Entry entry = it.next(); size += entry.getSize(); } return size; } @Override public Iterator<Entry> iterator() { return dir.iterator(); } @Override public Entry add(Entry entry) { dir.add(entry); return this; } } public interface Element { public abstract void accept(Visitor v); } import java.util.Iterator; public abstract class Entry implements Element { public abstract String getName(); public abstract int getSize(); public Entry add(Entry entry) throws Exception { throw new Exception(); } public Iterator<Entry> iterator() throws Exception { throw new Exception(); } @Override public String toString() { return getName() + "(" + getSize() + ")"; } } 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 void accept(Visitor v) { v.visit(this); } @Override public String getName() { return name; } @Override public int getSize() { return size; } } import java.util.Iterator; public class ListVisitor extends Visitor { private String currentdir = ""; @Override public void visit(File file) { System.out.println(currentdir + "/" + file.toString()); } @Override public void visit(Directory directory) { System.out.println(currentdir + "/" + directory.toString()); String savedir = currentdir; currentdir = currentdir + "/" + directory.getName(); Iterator<Entry> it = directory.iterator(); while (it.hasNext()) { Entry entry = it.next(); entry.accept(this); } currentdir = savedir; } } public class Main { public static void main(String[] args) { // 日本語はきちんと表示されているっぽい 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)); 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("Coposite.java", 200)); hanako.add(new File("game.doc", 400)); tomura.add(new File("memo.txt", 300)); tomura.add(new File("junk.mail", 4000)); rootdir.accept(new ListVisitor()); } } public abstract class Visitor { public abstract void visit(File file); public abstract void visit(Directory directory); }
/root(35000) /root/bin(30000) /root/bin/vi(10000) /root/bin/latex(20000) /root/tmp(0) /root/usr(5000) /root/usr/yuki(300) /root/usr/yuki/dialry.html(100) /root/usr/yuki/Coposite.java(200) /root/usr/hanako(400) /root/usr/hanako/game.doc(400) /root/usr/tomura(4300) /root/usr/tomura/memo.txt(300) /root/usr/tomura/junk.mail(4000)