読者です 読者をやめる 読者になる 読者になる

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)