http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=37809&forum=12&7
@ITでnagiseさんから「敷居が高いのでは」という声があって、確かに敷居が高いなと思うので、簡単な解説を書こうかなと思います。
まず、プロキシパターンについてですが、「いつ使うか分からないし、使わないかもしれない。生成コストが高いから、ギリギリまで生成したくない。でも、できればインスタンスの有無については意識したくない」ってときに有効になります。以下のような問題を抱えているコードがあるとします。
上記コードでは、利用する側でインスタンスを取得するとき、使うか使わないか分からない状態でも関係なしにCPUが重くなります。そこでプロキシパターンを適用すると以下のようなコードになります。
まずはプロキシクラスです。(あくまでサンプルコードなので同期処理とか考慮していません)
ファクトリを引数にしてインスタンスを生成しますが、getHoge()が呼ばれるまでファクトリを経由したインスタンスの生成を行いません。しかしこのクラスはHogeを実装しているので、Hogeのインスタンスとして利用できます。利用側のコードは以下のようになります。
と、こんな感じのコードになります。ここまでが、静的なプロキシです。次に説明するのが動的なプロキシになります。
動的なプロキシとは静的なプロキシとは違い、あらかじめプロキシクラスを用意する必要がありません。APIによって動的にクラスが生成される仕組みになっています。java.lang.reflect.Proxyクラスによって提供される機能です。上記コードはProxyクラスを使う事によって以下のように置き換えすることが出来ます。
この例では前のサンプルと違い、ファクトリを汎用化しました。何かのインスタンスを生成する汎用的なファクトリです。
ダイナミックプロキシでは型を用意するなくプロキシを生成する事ができますが、その代わり実装までは作る事が出来ません。なのでメソッドの呼び出しが発生したときに、変わりに呼び出されるハンドラを用意する必要があります。そのハンドラがjava.lang.reflect.InvocationHandlerで、そのハンドラを実装しているのが、上記のInvocationHandlerImplです。
ハンドラのインスタンスと、プロキシの対象となる型オブジェクトの配列と、生成したクラスをロードさせる為のクラスローダがあれば、ダイナミックプロキシのインスタンスを生成する事が出来ます。
ダイナミックプロキシではプロキシの対象と出来る型に制約があります。それはインターフェイス型のみが対象であるということです。具象クラスや抽象クラスではプロキシの対象とする事は出来ません。ですのでプロキシパターンを動的に適用する場合は必然的にインターフェイスの定義が必要になりますので注意が必要です。