今日は、プロキシデザインパターンとは何かを見てみましょう。その名の通り、プロキシは中間者を通じて誰かの代わりに何かを行うことを意味します。プログラムでは、プロキシオブジェクトを使用して特定のオブジェクトの特定のメソッドのアクセスを制御します。そのメソッドの前後でいくつかの追加処理を行うことができます。
- コンセプトの理解
- 静的プロキシ
- 動的プロキシ
コンセプトの理解#
- 抽象ロール:実際のロールとプロキシロールの共通メソッドを定義するために使用されます。
- 実際のロール:プロキシロールが呼び出すために実装する具体的なビジネスロジックです。
- プロキシロール:実際のロールを代理するために使用され、実際のロールの具体的なロジックの前後で追加の処理を行うことができます。
したがって、プロキシの意義は、具体的なビジネスロジックが必要な場合にのみ実際のロールの具体的なビジネスメソッドを呼び出すことであり、実際のロールの具体的なビジネスロジックとは関係のない処理はすべてプロキシクラスに含まれるということです。
静的プロキシ#
まず、静的プロキシのコード実装を見てみましょう。抽象ロールで共有のビジネスロジックを宣言します。具体的なコードは以下の通りです:
/**
* 抽象ロール
*/
public interface IBusiness {
/**
* 購入
*/
void buy();
}
次に、実際のロールを作成し、具体的なビジネスロジックを完成させます。具体的なコードは以下の通りです:
/**
* 実際のロール
*/
public class RealRole implements IBusiness{
@Override
public void buy() {
System.out.println("私は何かを買いたいです");
}
}
次に、プロキシロールを作成し、具体的なビジネスロジックを実行する際には必ず実際のロールのビジネスロジックメソッドを呼び出す必要があります。具体的なコードは以下の通りです:
/**
* プロキシロール
*/
public class ProxyRole implements IBusiness{
private IBusiness mRealRole;
public ProxyRole(IBusiness realRole) {
this.mRealRole = realRole;
}
@Override
public void buy() {
// 購入前の追加評価
System.out.println("購入前の追加評価...");
// 具体的なビジネスロジック
mRealRole.buy();
// 購入後の満足度調査
System.out.println("購入後の満足度調査...");
}
}
最後に、作成した静的プロキシクラスを使用します。具体的なコードは以下の通りです:
/**
* 静的プロキシのテスト
*/
public class StaticClient {
public static void main(String[] args) {
// 実際のロールを作成
IBusiness realRole = new RealRole();
// プロキシロールを作成
IBusiness proxyRole = new ProxyRole(realRole);
// 代理人が物を買ってくれる
proxyRole.buy();
}
}
テスト結果は以下の通りです:
購入前の追加評価...
私は何かを買いたいです
購入後の満足度調査...
この例では、プロキシは私たちが物を買うだけでなく、購入行動が発生する前後に追加の処理を行っています。非常に柔軟な方法ではないでしょうか。
動的プロキシ#
静的プロキシを学んだので、動的プロキシとの違いは何でしょうか。実際、静的プロキシと動的プロキシの主な違いは、静的プロキシは自分でプロキシクラスを生成する必要がありますが、動的プロキシはコードの実行中に自動的にプロキシクラスが生成されるという点です。動的プロキシの具体的な実装方法を見てみましょう。まず、Java JDK に付属している動的プロキシの実装のための 2 つの重要なクラスまたはインターフェースを見てみましょう。具体的なコードは以下の通りです:
// プロキシクラスとそのオブジェクトを動的に生成するために使用されます
java.lang.reflect.Proxy
// プロキシロールの呼び出し処理プログラムが実装する必要があるインターフェース
// 抽象ロールがメソッドを呼び出すときにこのインターフェースのinvokeメソッドが呼び出されます
java.lang.reflect.InvocationHandler
次に、Java JDK に付属している動的プロキシを実装してみましょう。まず、抽象ロールと実際のロールは静的プロキシと同じですので、ここでは省略します。次に、プロキシロールの呼び出し処理プログラム (InvocationHandler) を作成します。具体的なコードは以下の通りです:
/**
* プロキシロールの呼び出し処理プログラム
*/
public class BusinessHandler implements InvocationHandler{
private IBusiness mRealRole;
public BusinessHandler(IBusiness mRealRole) {
super();
this.mRealRole = mRealRole;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 購入前の追加評価
System.out.println("購入前の追加評価...");
// 実際のロールの具体的なビジネスロジック
method.invoke(mRealRole, args);
// 購入後の満足度調査
System.out.println("購入後の満足度調査...");
return null;
}
}
Proxy の静的メソッド newProxyInstance () を使用してプロキシオブジェクトを生成します。具体的なコードは以下の通りです:
/**
* Java JDKに付属している動的プロキシのテスト
*/
public class DynamicProxyClient {
public static void main(String[] args) {
// 実際のロールを作成
IBusiness mRealRole = new RealRole();
// ハンドラーインターフェースを作成
InvocationHandler handler = new BusinessHandler(mRealRole);
/**
* プロキシロールに対応するプロキシオブジェクトを取得します
* newProxyInstanceの引数(クラスローダー、自動生成されたプロキシクラスが実装するインターフェース、プロキシオブジェクトの呼び出し処理プログラム)
*/
IBusiness proxy = (IBusiness) Proxy.newProxyInstance(handler.getClass().getClassLoader(), mRealRole.getClass().getInterfaces(), handler);
// プロキシロールが物を買ってくれる
proxy.buy();
}
}
上記のコードの実行結果は以下の通りです:
購入前の追加評価...
私は何かを買いたいです
購入後の満足度調査...
静的プロキシの学習は、動的プロキシの学習に役立ちます。両者の主な違いは、動的プロキシはプロキシクラスを書く必要がなく、対応するプロキシクラスはコードの実行中に動的に生成されるということです。もちろん、生成されたプロキシクラスも抽象ロールに対応するインターフェースを実装しています。同時に、プロキシロールの呼び出し処理プログラム (InvocationHandler) も具体的なビジネスロジックを引き継ぎます。静的プロキシと動的プロキシについては以上です。