目次へ

13.Visitor パターン

  • 2012/04/26 一部修正しました

13.1 Visitor パターンとは

第13章では Visitor パターンを学びます。Visitor とは、英語で「訪問者」を意味します。Visitor パターンでは、「処理」を訪問者である Visitor オブジェクトに記述することで、処理の追加を簡単にします。処理対象となる、Acceptor オブジェクトは、Visitor オブジェクトを受け入れる accept(Visitor visitor)メソッドを実装している必要があります。

例えば、家の「水道工事」を行ってもらう場合、あなたは、「水道工事業者」を家に呼んで、「よろしくお願いします。」と言って、後は全てお任せしますよね。同様に、「庭の手入れ」を行ってもらう場合は、「庭師」を家に呼んで、全てお任せしてしまうでしょう。そのほかにも、電気工事業者を呼ぶことも、リフォーム業者を呼ぶこともあるでしょう。これらの訪問者に対して、あなたは、「では、よろしく」と言って、ほとんどの作業をお任せするはずです。

お任せの仕方に多少の違いがあるかもしれませんが、最終的には、全てを業者にお任せすることになると思います。もし、新しいサービスを提供する業者が現れたときにも、各家庭は、なんら態度を変える必要が無く、その業者を呼んで、「よろしくお願いします。」というだけで、その新しいサービスを受けることができます。

Visitor パターンでは、このように、受け入れる側に処理を追加することなく、処理を追加することができるパターンです。

13.2 サンプルケース

サンプルケースでは、家庭訪問を例に考えて見ます。各家庭では、先生であろうと、近所のおばちゃんであろうと、訪問者が訪れると、知らない人でなければ、「いらっしゃい」と言って受け入れます。この際、各家庭を Acceptor 、先生を Visitor として、Visitor パターンに当てはめて考えて見ます。Visitor パターンでは、Visitor は、訪問対象となる、家庭を訪問します。訪問された家庭は、「ようこそいらっしゃいました」と先生を受けいれます。

さて、新人先生の小学校でも、秋の家庭訪問の時期がやってきました。新人先生も、初めての家庭訪問にどきどきしながら、各家庭を訪れました。

新人先生 こ・こ・こ・こんにちわ
親御さん

あら、いらっしゃい新人先生。どうかなさいましたか?青い顔して・・・。

新人先生 い・・いえ、緊張して。
親御さん あら、先生ったらかわいい。

各家庭の親御さんたちは、新人先生がどきどきしているのをあざ笑うかのように冷静です。新人先生は、何で自分だけこんなにどぎまぎしているのだろうと不思議に思い、学校に帰ってベテラン先生に聞きました。

新人先生 ベテラン先生、家庭訪問したとき、なぜ親御さんたちは、すごく冷静ですね。
私は、なんだかどぎまぎしちゃって。
ベテラン先生 それは、当たり前だよ。 君は、自分の家に、誰か訪問してきたとき、そんなにどきどきするかい?
新人先生 いえ、人が訪問してくるのは別に
ベテラン先生

だよね。今回、初めての経験をしているのは、君だけで、 親御さんたちは、これまで何回も家庭訪問を受けている。 少なくとも、去年は受けているだろうし、もしかしたら、兄弟などを合わせると、 既に10回以上の家庭訪問を受けている方もおられるかも知れない。 親御さんたちは、これまで、先生方を受け入れてきたのと同じように、 君を受け入れているわけだね。 メソッドで表すと、 accept(Teacher teacher) となるだろうか。 このように、先生を受け入れるメソッドを既に持っている家庭は、 違う兄弟の家庭訪問や、違う先生の家庭訪問でも、 なんら別のメソッドを用意する必要がないわけだね。

新人先生

なるほど。
どの先生が来るかによって、いろいろとメソッドを用意していたら、
親御さんたちも大変ですよね。

さて、ではこの状況をクラスで表現してみましょう。

//先生クラス
import java.util.List;

public abstract class Teacher{
	List students = null;
	public abstract void visit(Home studentHome);
	public abstract void visit(TanakaHome studentHome);
	public abstract void visit(SuzukiHome studentHome);
	public List getStudentList(){
		return students;
	}

} 
//新人先生クラス
import java.util.List;

public class RookieTeacher extends Teacher{
	List students = null;
	public RookieTeacher(List students){
		this.students = students;
	}
	public void visit(Home studentHome){
		System.out.println("こんにちは");
	}
	public void visit(TanakaHome studentHome){
		studentHome.praisedChild();
	}
	public void visit(SuzukiHome studentHome){
		studentHome.reprovedChild();
	}
} 
//家庭クラス
public abstract class Home{
	public abstract Object praisedChild();
	public abstract Object reprovedChild();
}
//受け入れインタフェース
public interface TeacherAcceptor{
	public void accept(Teacher teacher);
}
//鈴木さんの家庭
public class SuzukiHome extends Home implements TeacherAcceptor{
	public Object praisedChild(){
		System.out.println("あら、先生ったらご冗談を");
		return new Tea();
	}
	public Object reprovedChild(){
		System.out.println("うちの子に限ってそんなことは・・・。");

		return null;
	}
	/**
	 * 訪問者を受け入れるメソッド
	 */
	public void accept(Teacher teacher){
		teacher.visit(this);
	} 
}

新人先生を表す RookieTeacher クラスでは、visit メソッドがオーバーロードされており、訪問する家庭によって visit メソッドが選択されます。クラス図は、以下のようになります。

サンプルケースクラス図

新しい先生が赴任してきた場合も、各家庭は、なんら変更を必要としませんね。

13.3 Visitor パターンまとめ

Visitor パターンの一般的なクラス図は以下のようになります。

クラス図
[引用] 『Java言語で学ぶ デザインパターン入門』(結城浩 ソフトバンクパブリッシング株式会社出版 2001年)

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp