13.Visitor パターン
- 2012/04/26 一部修正しました
- 13.1 Visitor パターンとは
- 13.2 サンプルケース
- 13.3 Visitor パターンまとめ
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年)