1. 代理店モデル
いわゆる代理店とは、他の人または別の組織に代わって行動を起こす個人または組織です。場合によっては、クライアントがオブジェクトを直接参照したくない、または参照できない場合、プロキシ オブジェクトがクライアントとターゲット オブジェクトの間の仲介者として機能することがあります。
プロキシ モードはオブジェクトにプロキシ オブジェクトを提供し、プロキシ オブジェクトは元のオブジェクトへの参照を制御します。
実生活の例: 春節中は残業でとても忙しく、電車の切符を買う時間がありません。そのような時は、近くの発券センターに電話して、行きの電車の切符を買ってもらうことができます。もちろん、これには追加料金がかかります。ただし、チケット センター自体がチケットを販売しているのではなく、実際にチケットを販売しているのは鉄道駅だけであることは明らかです。これは重要なポイントです!
上記の例では、あなたは「顧客」、チケットセンターは「エージェントの役割」、駅は「実際の役割」、そしてチケットの販売は「抽象的な役割」と呼ばれます。
エージェント モードの Java コード例:
抽象ロール: 抽象クラスまたはインターフェイス
interface Business { void doAction(); }
実際のロール: ビジネス ロジック インターフェイスを真に実装します
エージェント ロール: ビジネス ロジック インターフェイス自体は実装しませんが、実際のロールを呼び出します実装してください
class BusinessImplProxy implements Business { private BusinessImpl bi; public void doAction() { if (bi==null) { bi = new BusinessImpl(); } doBefore(); bi.doAction(); doAfter(); } public void doBefore() { System.out.println("前置处理!"); } public void doAfter() { System.out.println("后置处理!"); } } //测试类 class Test { public static void main(String[] args) { //引用变量定义为抽象角色类型 Business bi = new BusinessImplProxy(); bi.doAction(); } }
<span></span>
そこで、JVM のサポートにより、プロキシ クラス (「エージェント ロール」) を実行時に動的に生成でき、動的プロキシを使用した後、上記のプロキシ モードでのコード拡張の問題を解決できます。 「エージェント ロール」は必要ありません。手動で生成されますが、クラス ローダー、インターフェイス配列、呼び出しハンドラーの 3 つのパラメーターを指定することにより、実行時に JVM によって動的に生成されます。
動的プロキシ モード JAVA コードの例:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Method; //抽象角色:java动态代理的实现目前只支持接口,不支持抽象类 interface BusinessFoo { void foo(); } interface BusinessBar { String bar(String message); } //真实角色:真正实现业务逻辑方法 class BusinessFooImpl implements BusinessFoo { public void foo() { System.out.println("BusinessFooImpl.foo()"); } } class BusinessBarImpl implements BusinessBar { public String bar(String message) { System.out.println("BusinessBarImpl.bar()"); return message; } } //动态角色:动态生成代理类 class BusinessImplProxy implements InvocationHandler { private Object obj; BusinessImplProxy() { } BusinessImplProxy(Object obj) { this.obj = obj; } public Object invoke(Object proxy,Method method,Object[] args) throws Throwable { Object result = null; doBefore(); result = method.invoke(obj,args); doAfter(); return result; } public void doBefore(){ System.out.println("do something before Business Logic"); } public void doAfter(){ System.out.println("do something after Business Logic"); } public static Object factory(Object obj) { Class cls = obj.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj)); } } //测试类 public class 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); String message = bb.bar("Hello,World"); System.out.println(message); } }
プログラム フローの説明:
new BusinessFooImpl(); 「実際のロール」を作成し、それをファクトリ メソッド BusinessImplProxy.factory() に渡し、「呼び出しプロセッサ」を初期化します。つまり、InvocationHandler のクラスを実装します。また、動的に作成されたプロキシ クラス インスタンスを返します。「エージェント ロール」は、「抽象ロール」によって提供されるビジネス ロジック メソッドも実装する必要があるため、BusinessBar に変換して、BusinessBar タイプを指す参照 bb に割り当てることができます。
newProxyInstance(ClassLoaderloader, Class>[] Interfaces, InvocationHandler h) メソッドを使用すると、プログラマはパラメータを指定して必要なプロキシ クラスを動的に返すことができますが、invoke(Object proxy, Method method, Object[] args) メソッドは実行時に JVM によって動的に呼び出されます。 「bb.bar("Hello,World");」メソッドが実行されると、JVM は動的に「呼び出しプロセッサ」を割り当て、外部呼び出しにパラメータを渡し、method.invoke(obj, args) を呼び出して実際に実行します。 !
BusinessImplProxy.Factory 静的メソッドは、さまざまなビジネス ロジック インターフェイス BusinessFoo および BusinessBar に従って、プロキシ クラス (「エージェント ロール」) を動的に生成するために使用されます。プロキシ ロールは実行時に動的に生成されます。 「抽象ロール」、「エージェントロール」、呼び出しハンドラー(InvocationHandlerインターフェースを実装したクラス)はすべて変更できるため、JAVAの動的プロキシは非常に強力です。
Java プロキシ モードとダイナミック プロキシ モードの詳細については、PHP 中国語 Web サイトを参照してください。