Visitorパターン

###Visitorパターンとは
データ構造と処理を分離する。
データ構造を巡り歩く訪問者を表すクラスを用意し、そのクラスに処理を任せる。
データ構造側は、訪問者を受け入れてやる。

###Visitor(訪問者)の役
Visitor役はデータ構造の具体的な要素(ConcreteElement役)ごとに「xxxを訪問した」という
visit(xxx)メソッドを宣言する。
visit(xxx)はxxxを処理するためのメソッドで、実際のコードはConcreteVisit役の側に書かれる。

````java
package visitor;

public abstract class Visitor {
	public abstract void visit(File file);
	public abstract void visit(Directory directory);
}
````

###ConcreteVisitor(具体的訪問者)の役
ConcreteVisitor役はVisitor役のインターフェースを実装する。
visit(xxx)という形のメソッドを実装し、個々のConcreteElement役ごとの処理を記述する。


````java
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;
	}
}
````

###Element(要素)の役
Element役はVisitor役の訪問先を表す役。
訪問者を受け入れるacceptメソッドを宣言する。
acceptメソッドの引数にはVisitor役が渡される。

````java
package visitor;

public interface Element {
	public abstract void accept(Visitor v);
}
````

###ConcreteElement(具体的要素)の役
ConcreteElement役はElement役のインターフェースを実装する役。

````java
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);
	}
}
````

````java
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);
	}
}
````

###ObjectStructure(オブジェクト構造)の役
ObjectStructure役はElement役の集合を扱う役。
ConcreteVisitor役が個々のElement役を扱えるようなメソッドを備えている。
この役は上記のDirectoryクラスが該当する。

###呼び出し元

````java
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();
		}
	}
}
````

###実行結果

![スクリーンショット 2020-09-16 18.12.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/1a59c690-9b99-90b2-2ff3-ffe5a07b94db.png)

https://github.com/aki0207/visitor

こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80">増補改訂版Java言語で学ぶデザインパターン入門</a>