1. エージェントモード
エージェントとは、別の個人または機関に代わって行動する個人または機関です。場合によっては、クライアントがオブジェクトを直接参照したくない、またはオブジェクトを直接参照できない場合、プロキシ オブジェクトがクライアントとターゲット オブジェクトの間の仲介者として機能することがあります。
プロキシ パターンはオブジェクトのプロキシ オブジェクトを提供し、プロキシ オブジェクトは元のオブジェクトへの参照を制御します。
実生活での例: 年末年始は残業で忙しく、電車の切符を買う時間がないときは、近くのチケットセンターに電話して、帰りの電車の切符を買ってもらうことができます。追加の人件費を追加します。ただし、チケット センター自体がチケットを販売しているのではなく、実際にチケットを販売しているのは鉄道駅だけであることは明らかです。これはとても重要です!
上の例では、あなたは「顧客」、チケットセンターは「代理店の役割」、駅は「現実の役割」、そしてチケットの販売は「抽象的な役割」と呼ばれます。
エージェント モードの Java コード例:
抽象的な役割: 抽象クラスまたはインターフェイス
次のようにコードをコピーします。
インターフェースビジネス
{
void doAction();
}
実際の役割: ビジネス ロジック インターフェイスを真に実装します。
エージェント ロール: ビジネス ロジック インターフェイスを実装しませんが、実際のロールを呼び出して実装します。
次のようにコードをコピーします。
クラス BusinessImplProxy は Business を実装します
{
プライベート BusinessImpl bi;
public void doAction()
{
if (bi==null)
{
bi = 新しい BusinessImpl();
}
doBefore();
bi.doAction();
doAfter();
}
public void doBefore()
{
System.out.println("前処理中!");
}
public void doAfter()
{
System.out.println("後処理!");
}
}
//テストクラス
クラステスト
{
public static void main(String[] args)
{
//参照変数は抽象ロール型として定義されます
ビジネス bi = new BusinessImplProxy();
bi.doAction();
}
}
次のようにコードをコピーします。
<スパン></スパン>
したがって、JVM のサポートにより、プロキシ クラス (「エージェント ロール」) を実行時に動的に生成でき、動的プロキシを使用した後は、上記のプロキシ モードでのコード拡張の問題を解決できます。手動で生成されます。これは、クラス ローダー、インターフェイス配列、および呼び出しハンドラーの 3 つのパラメーターを指定することによって、実行時に JVM によって動的に生成されます。
動的プロキシ モードの Java コード例:
次のようにコードをコピーします。
インポート java.lang.reflect.InvocationHandler;
java.lang.reflect.Proxyをインポートします。
java.lang.reflect.Methodをインポートします。
//抽象ロール: Java 動的プロキシの実装は現在インターフェイスのみをサポートしており、抽象クラスはサポートしていません
インターフェース BusinessFoo
{
void foo();
}
インターフェースビジネスバー
{
文字列バー(文字列メッセージ);
}
//実際の役割: ビジネス ロジック メソッドを実際に実装する
クラス BusinessFooImpl は BusinessFoo を実装します
{
パブリック void foo()
{
System.out.println("BusinessFooImpl.foo()");
}
}
クラス BusinessBarImpl は BusinessBar を実装します
{
public String bar(文字列メッセージ)
{
System.out.println("BusinessBarImpl.bar()");
返信メッセージ;
}
}
//動的ロール: プロキシ クラスを動的に生成
クラス BusinessImplProxy は InvocationHandler を実装します
{
プライベートオブジェクトオブジェクト;
BusinessImplProxy() {
}
BusinessImplProxy(オブジェクト obj) {
this.obj = obj;
}
public Object invoke(Object proxy,Methodメソッド,Object[] args) throws Throwable
{
オブジェクトの結果 = null;
doBefore();
結果 = メソッド.invoke(obj,args);
doAfter();
結果を返します。
}
public void doBefore(){
System.out.println("ビジネス ロジックの前に何かを行う");
}
public void doAfter(){
System.out.println("ビジネス ロジックの後に何かを行う");
}
public static オブジェクトファクトリー(オブジェクトobj)
{
クラス cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
}
}
//テストクラス
パブリック クラス DynamicProxy
{
public static void main(String[] args) throws Throwable
{
BusinessFooImpl bfoo = new BusinessFooImpl();
BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bfoo);
bf.foo();
System.out.println();
BusinessBarImpl bbar = new BusinessBarImpl();
BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
文字列メッセージ = bb.bar("Hello,World");
System.out.println(メッセージ);
}
}
プログラムフローの説明:
new BusinessFooImpl(); は、「実際のロール」を作成し、それをファクトリ メソッド BusinessImplProxy.factory() に渡し、次に、InvocationHandler を実装するクラスである「呼び出しプロセッサ」を初期化します。また、動的に作成されたプロキシ クラス インスタンスを返します。「エージェント ロール」は、「抽象ロール」によって提供されるビジネス ロジック メソッドも実装する必要があるため、BusinessBar に変換して、BusinessBar タイプを指す参照 bb に割り当てることができます。
newProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh) メソッドを使用すると、プログラマはパラメータを指定して必要なプロキシ クラスを動的に返すことができます。一方、invoke(Object proxy, Method method, Object[] args) メソッドは、によって使用されます。 JVM は実行時に動的に呼び出されます。 「bb.bar("Hello,World");」メソッドを実行すると、JVM は動的に「呼び出しハンドラー」を割り当て、外部呼び出しにパラメーターを渡し、method.invoke(obj, args) を呼び出して実際に実行します。
BusinessImplProxy.Factory 静的メソッドは、プロキシ クラス (「エージェント ロール」) を動的に生成するために使用されます。プロキシ ロールは、異なるビジネス ロジック インターフェイス BusinessFoo および BusinessBar に基づいて実行時に動的に生成されます。 「抽象ロール」、「エージェントロール」、呼び出しハンドラー(InvocationHandlerインターフェースを実装したクラス)はすべて変更できるため、JAVAの動的プロキシは非常に強力です。