「Visitor」という英単語は、「訪問者」を意味します。
このパターンは、「データ構造」と「それに対する処理」を分離することを目的とするパターンです。そのためこのパターンを適用すると、「データ構造」を変更することなしに、「新しい処理」を追加することができます。
具体的には、訪問者であるVisitor役のオブジェクトが、訪問先であるデータ構造要素の個々のオブジェクトを訪問し、その訪問先の公開されている資源を利用して処理を実行して回るという形になります。(データ構造役オブジェクトは、処理を訪問者役オブジェクトに委任する)
具体的なデータ構造の要素(ConcreteAcceptorA・ConcreteAcceptorB)毎に訪問して行う処理(visitメソッド)のインタフェースを定義します。
※visitメソッドは、 オーバーロードする事でその訪問先要素の型に応じた処理を指定します。
Visitorパターンのクラス図
Visitorパターンのシーケンス図
Visitorパターンでは、受入者「ConcreteAcceptor」のメソッドacceptを呼出すと、訪問者「ConcreteVisitor」のメソッドvisitが呼出され、実行する処理が決定します。この様な2重呼出しを一般的に「ダブルディスパッチ(2重振分け)」と呼びます。
1. Visitor.java
public abstract class Visitor { public abstract void visit(ConcreteAcceptorA acceptorA); public abstract void visit(ConcreteAcceptorB acceptorB); }
2-1. ConcreteVisitorA.java
public class ConcreteVisitorA extends Visitor { private String name = "ConcreteVisitorA"; public void visit(ConcreteAcceptorA acceptorA) { System.out.println(name + " が " + acceptorA.getName() + " を訪問しました。"); } public void visit(ConcreteAcceptorB acceptorB) { System.out.println(name + " が " + acceptorB.getName() + " を訪問しました。"); } }
2-2. ConcreteVisitorB.java
public class ConcreteVisitorB extends Visitor { private String name = "ConcreteVisitorB"; public void visit(ConcreteAcceptorA acceptorA) { System.out.println(name + " が " + acceptorA.getName() + " に参りました。"); } public void visit(ConcreteAcceptorB acceptorB) { System.out.println(name + " が " + acceptorB.getName() + " に参りました。"); } }
3. Acceptor.java
public abstract class Acceptor { public abstract void accept(Visitor visitor); }
4-1. ConcreteAcceptorA.java
public class ConcreteAcceptorA extends Acceptor { private String name = "ConcreteAcceptorA"; public String getName() { return name; } public void accept(Visitor visitor) { visitor.visit(this); } }
4-2. ConcreteAcceptorB.java
public class ConcreteAcceptorB extends Acceptor { private String name = "ConcreteAcceptorB"; public String getName() { return name; } public void accept(Visitor visitor) { visitor.visit(this); } }
5. Client.java
public class Client { public static void main(String[] args) { Visitor viA = new ConcreteVisitorA(); Visitor viB = new ConcreteVisitorB(); Acceptor acA = new ConcreteAcceptorA(); Acceptor acB = new ConcreteAcceptorB(); acA.accept(viA); acB.accept(viA); acA.accept(viB); acB.accept(viB); } }
C:\sample\desin_pattern\visitor>javac Client.java [Enter] C:\sample\desin_pattern\visitor>java Client [Enter] ConcreteVisitorA が ConcreteAcceptorA を訪問しました。 ConcreteVisitorA が ConcreteAcceptorB を訪問しました。 ConcreteVisitorB が ConcreteAcceptorA に参りました。 ConcreteVisitorB が ConcreteAcceptorB に参りました。