• このエントリーをはてなブックマークに追加

スポンサードリンク

はじめに

今日、仕事でVisitorパターンの話題がでたけど なんのことだかわからなかったので、調べてみた.

Visitor Patternとは

ビジターパターンとは、Gofのデザインパターンの一つ.

データと処理の分離

ひとつの特徴は、データと処理を分離できること。

  • データに対応するのが、Accepter.
  • 操作に対応するのが, Visitor

よくあるVisitorパターンの例は、 コンポジットパターン(フォルダパターン)に対する操作.

  • データは,
    • フォルダ
    • ファイル
  • 操作は、
    • 最終更新日取得
    • 作成日取得
    • サイズ取得

型のパターンマッチのカプセル化

Visitorパターンは関数型言語ででてくる, 型によるパターンマッチにとても似ていると思った.

Accepterごとに異なる型を持たせ、 Visitorは型のパターンマッチによって型に対するメソッドを 割り当てるイメージ.

Code

class VisitorSample {

	////////////////////
	// Data
	////////////////////
	abstract public static class PrintData {
		 abstract public void accept(Visitor printer);
	}
	
	public static class Data1 extends PrintData {
		
		public String getStr1 () {
			return "Suzuki";
		}

		public String getStr2 () {
			return "Ichiro";
		}

		public void accept(Visitor printer) {
			printer.visit(this);
		}
	}

	public static class Data2 extends PrintData {
		public String getStr () {
			return "Jonney";
		}

		public void accept(Visitor printer) {
			printer.visit(this);
		}		
	}

	////////////////////
	// Operation
	////////////////////
	public interface Visitor {
		public void visit(Data1 data);
		public void visit(Data2 data);	
	}
	
	public static class NamePrinter implements Visitor {
		public void visit(Data1 data) {
			String str1 = data.getStr1();
			String str2 = data.getStr2();
			System.out.println(str1 + " " + str2);
		}

		public void visit(Data2 data) {
			String str = data.getStr();
			System.out.println(str);			
		}
	}

	////////////////////
	// Main procedre
	////////////////////
	public static void main(String[] args) {
		NamePrinter printer = new NamePrinter();
		PrintData data;
	
		data = new Data1();
		data.accept(printer);
		
		data = new Data2();
		data.accept(printer);
	}
}

操作の柔軟な追加

Visitorを継承することで、容易に操作を追加することができる。 上の例では、名前の表示という操作がすでにある. ここに、出席番号表示という操作を追加する.

Code

class VisitorSample {

	////////////////////
	// Data
	////////////////////
	abstract public static class PrintData {
		abstract public void accept(Visitor printer);
		abstract public int getNum();		
	}
	
	public static class Data1 extends PrintData {
		
		public String getStr1 () {
			return "Suzuki";
		}

		public String getStr2 () {
			return "Ichiro";
		}

		public int getNum () {
			return 1;
		}
		
		public void accept(Visitor printer) {
			printer.visit(this);
		}
	}

	public static class Data2 extends PrintData {
		public String getStr () {
			return "Jonney";
		}
		
		public int getNum () {
			return 2;
		}

		public void accept(Visitor printer) {
			printer.visit(this);
		}		
	}

	////////////////////
	// Operation
	////////////////////
	public interface Visitor {
		public void visit(Data1 data);
		public void visit(Data2 data);	
	}
	
	public static class NamePrinter implements Visitor {
		public void visit(Data1 data) {
			String str1 = data.getStr1();
			String str2 = data.getStr2();
			System.out.println(str1 + " " + str2);
		}

		public void visit(Data2 data) {
			String str = data.getStr();
			System.out.println(str);			
		}
	}

	public static class NumberPrinter implements Visitor {
		public void visit(Data1 data) {
			System.out.println("出席番号: " + data.getNum());
		}

		public void visit(Data2 data) {
			System.out.println("出席番号: " + data.getNum());			
		}
	}
	
	////////////////////
	// Main procedre
	////////////////////
	public static void main(String[] args) {
		NamePrinter name = new NamePrinter();		
		NumberPrinter num = new NumberPrinter();
		PrintData data;
	
		data = new Data1();
		data.accept(name);		
		data.accept(num);
		
		data = new Data2();
		data.accept(name);		
		data.accept(num);
	}
}

さいごに

だれがこんな手法を考えついたのだろう??

デザインパターンってすごいね-。