21.Proxyパターン
- 2012/04/26 一部修正しました
- 21.1 Proxyパターンとは
- 21.2 サンプルケース
- 21.3 Proxyパターンまとめ
2.1 Proxyパターンとは
第21章ではProxyパターンを学びます。Proxyとは「代理人」という意味です。現実世界で代理人というと、弁護士や税理士など本人ができない仕事をするというイメージがありますが、Proxyパターンにおける代理人オブジェクトは、本人でなくてもできるような処理を任されます。そして代理人オブジェクトでできない処理は本人オブジェクトが引き受け、処理します。
Proxyパターンは、要求を代理人オブジェクトが受け取って処理するパターンです。
21.2 サンプルケース
今日は、新人の藤原さんが担任の山田先生の代わりに授業を行うことになりました。
| 山田先生 | : | 皆さん、おはようございます。今日の授業は、藤原先生にお願いすることになりました。まずは、自己紹介をどうぞ。 |
| 藤原先生 | : | こんにちは、藤原です。私は15年前にこの学校を卒業しました。当時とあまり変わっていなくて、懐かしいです。今日は1日、よろしくお願いします。 |
| 生徒 | : | よろしくお願いしまーす。 |
| 山田先生 | : | それでは、授業を始めましょう。みなさん、みなさん、いつもどおり授業を受けましょうね。 |
| 生徒 |
:
|
はーい。 |
| 藤原先生 |
:
|
では、始めたいと思います。教科書の25ページを開いてください。 |
| ・ ・ ・ |
順調にスタートしました。藤原先生も始めは緊張していたようですが、徐々に自分のペースになってきたようです。
|
・ |
||
| 藤原先生 |
:
|
・・・というわけで3時間目の授業は以上です。みなさん、わかりましたか? |
| 美保さん |
:
|
先生、「問題1」がわかりません。 |
| 藤原先生 |
:
|
それは「~~解答1~~」です。 |
| 一郎くん |
:
|
「問題2」ってどういうことですか? |
| 藤原先生 |
:
|
それは「~~解答2~~」です。 |
| 隆くん |
:
|
じゃあ、「問題3」はどうすればいいですか? |
| 藤原先生 |
:
|
(うっ、どう答えればいいんだろう・・・)えー、それについては次の時間にお話しますね。 |
どうやら藤原先生は隆くんの質問には答えられなかったようです。職員室に戻った藤原先生は、こっそり山田先生に聞いてみました。
| 藤原先生 |
:
|
「問題3」についてなんですが、どう答えればよいでしょうか? |
| 山田先生 |
:
|
それなら「〜〜解答3〜〜」と説明してあげればよいでしょう。 |
| 藤原先生 |
:
|
なるほど、わかりました。 |
休み時間も終わり、再び授業再開です。
| 藤原先生 |
:
|
先ほどの質問3についてですが、答えは「~~解答3~~」となります。 |
| 隆くん |
:
|
はい、わかりました。ありがとうございます。 |
| 藤原先生 |
:
|
(ほっ・・・)それでは、次の授業を始めますね。・・・ |
無事に質問にも答えることができ、授業を再開できました。藤原先生も一安心です。
さて、すでにお気づきの方も多いと思いますが、今回の例では、山田先生が本人オブジェクト、藤原先生が代理人オブジェクトとなっています。生徒(クライアント)からの質問(メソッド呼び出し)に対し、藤原先生がわかることは答え、分からないことは山田先生に聞き、その答を生徒に伝える、という流れです。たとえば山田先生がとても忙しいとき、生徒からの質問に藤原先生がいくつか答えられれば、山田先生はすべての質問に答えなくても良いので少し楽になりますね。以下にクラス図を示します。

山田先生クラスと藤原先生クラスは、ともに先生インターフェースを実装しています。そのため、生徒は山田先生と藤原先生を区別する必要なく、同じように質問することができるのです。以下にソースを示します。
//先生インターフェース
public interface Teacher {
public void question1();
public void question2();
public void question3();
}
//山田先生クラス(本人オブジェクト)
public class Yamada implements Teacher {
public void question1() {
System.out.print("~~解答1~~");
}
public void question2() {
System.out.print("~~解答2~~");
}
public void question3() {
System.out.print("~~解答3~~");
}
}
//藤原先生クラス(代理人オブジェクト)
public class Fujiwara implements Teacher {
private Teacher yamada = new Yamada();
public void question1() {
System.out.println("それは「~~解答1~~」です。");
}
public void question2() {
System.out.println("それは「~~解答2~~」です。");
}
public void question3() {
System.out.print("答えは「");
//藤原先生には答えられないので、山田先生に聞く
yamada.question3();
System.out.println("」となります。");
}
}
//生徒クラス(クライアント)
public class Student {
public static void main(String[] args) {
Teacher fujiwara = new Fujiwara();
//質問1
fujiwara.question1();
//質問2
fujiwara.question2();
//質問3
fujiwara.question3();
}
}
実習課題1
今日は山田先生が午後の5時間目から出張です。そこで、藤原先生は分かる質問1と2には答えて、分からない質問3については午前中は山田先生に聞き、午後からは「明日、返答します。」という返事を返すように改良してください。
解答例
Proxyパターンの意味から考えて、修正するのは、藤原先生クラス(代理人オブジェクト)で、山田先生クラス(本人オブジェクト)は変更しません。
import java.util.Calendar;
//藤原先生クラス(代理人オブジェクト)
public class Fujiwara implements Teacher {
private Teacher yamada = new Yamada();
public void question1() {
System.out.println("それは「~~解答1~~」です。");
}
public void question2() {
System.out.println("それは「~~解答2~~」です。");
}
public void question3() {
Calendar now = Calendar.getInstance();
if (Calendar.AM == now.get(Calendar.AM_PM)) {
//午前中は山田先生に聞く
System.out.print("答えは「");
yamada.question3();
System.out.println("」となります。");
} else {
//午後からは返答を明日にする
System.out.println("明日、返答します。");
}
}
}
生徒は山田先生が午後から出張であることを意識する必要はありません。山田先生に質問するのと同じように、いつでも藤原先生に聞くことができます。
21.3 Proxyパターンまとめ
Proxy パターンの一般的なクラス図は以下のようになります


