JAva(20)-エージェントモード
5865 ワード
一.エージェントモード:
≪プロキシ・モード・モード|Proxy Mode Mode|emdw≫:他のオブジェクトへのアクセスを制御するプロキシを提供します.すなわち,仲介によってこのオブジェクトの使用を制御する.
エージェント・モードの役割は次のとおりです.
1).抽象ロール:リアルオブジェクトとエージェントオブジェクトのインタフェースを宣言します(抽象クラスも使用できます).
2).エージェントロール:エージェントオブジェクトロールの内部には、実際のオブジェクトロールへの参照が含まれています.これにより、実際のオブジェクトを操作しながら、エージェントオブジェクトが実際のオブジェクトとのインタフェースを提供し、いつでも実際のオブジェクトに代わることができます.また、プロキシオブジェクトは、実際のオブジェクト操作を実行するときに、実際のオブジェクトのカプセル化に相当する他の操作を追加できます.
3).リアルロール:エージェントロールが表すリアルオブジェクトは、私たちが最終的に参照するオブジェクトです.
静的プロキシ・モードの実装:
抽象クラスまたはインタフェース(抽象クラスで実装):
実際の役割:
プロキシロール:
テストクラス:
印刷:
これは静的エージェントモードであり、静的エージェントモードには大きな弊害がある.このエージェントモードを使用すると、実際のロールは実装されなければならないため、エージェントオブジェクトの内部属性として使用され、実際のロールがエージェントロールに対応し、大量のリソースの浪費をもたらす.これによりダイナミックエージェントモードが作成されます.
動的プロキシ・モード:
JAvaダイナミックエージェントクラスはjava.lang.reflectパッケージの下にあります.主に2つのクラスの使用に関連しています.
1).Interface InvocationHandler:このインタフェースには1つのメソッドしか定義されていません
public Object invoke(Object obj,Method method,Object[] args)
実際の使用では、第1のパラメータobjは一般的に値エージェントクラスであり、第2のパラメータmethodは被エージェントの方法であり、第3のパラメータargs[]はこの方法のパラメータ配列を指す.この方法はエージェントクラスで動的に実装される.
2).Proxy:このクラスは動的エージェントクラスです.前例のProxyRoleのようなものです.
使用する方法:
protected Proxy(InvocationHandler h):内部のhに値を割り当てるための構造関数.
static Class getProxyClass(ClassLoader loader,Class[]interface):loaderはクラスローダであり、interfaceは実際のクラスが所有するすべてのインタフェースの配列であるエージェントクラスを取得します.
static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h):エージェントクラスのインスタンスを返し、返されたエージェントクラスをエージェントクラスとして使用できます.
動的エージェントクラス:
インタフェース:
実際の役割:
動的プロキシロール:
テストクラス:
このようにして,エージェントされたオブジェクト(RealSubject)を実行時に動的に変更することができ,制御が必要なインタフェース(Subjectインタフェース)を実行時に変更することができ,制御の方式(DynamicSubject)を動的に変更することができ,柔軟な動的代理モードを実現することができる.
動的エージェントクラス(Dynamic Proxy)とは、実行時に生成されたclassであり、生成時にinterfaceのセットを提供する必要があり、classはこれらのinterfaceを実現したと主張します.もちろん、このClassのインスタンスをこれらのinterfaceのいずれかとして使用することができます.もちろん、このDynamic Proxyは実はProxyで、それはあなたのために実質的な仕事をすることはありません.そのインスタンスを生成するときはhandlerを提供しなければなりません.それによって実際の仕事を引き継ぐ必要があります.
動的エージェント・モードの役割:ログとビジネスの分離、すなわちクラスが特定のビジネスを提供するだけであることを実現します.
動的エージェントの別の例:
印刷:
≪プロキシ・モード・モード|Proxy Mode Mode|emdw≫:他のオブジェクトへのアクセスを制御するプロキシを提供します.すなわち,仲介によってこのオブジェクトの使用を制御する.
エージェント・モードの役割は次のとおりです.
1).抽象ロール:リアルオブジェクトとエージェントオブジェクトのインタフェースを宣言します(抽象クラスも使用できます).
2).エージェントロール:エージェントオブジェクトロールの内部には、実際のオブジェクトロールへの参照が含まれています.これにより、実際のオブジェクトを操作しながら、エージェントオブジェクトが実際のオブジェクトとのインタフェースを提供し、いつでも実際のオブジェクトに代わることができます.また、プロキシオブジェクトは、実際のオブジェクト操作を実行するときに、実際のオブジェクトのカプセル化に相当する他の操作を追加できます.
3).リアルロール:エージェントロールが表すリアルオブジェクトは、私たちが最終的に参照するオブジェクトです.
静的プロキシ・モードの実装:
抽象クラスまたはインタフェース(抽象クラスで実装):
public abstract class Nozzle {
// 。
public abstract void role();
}
実際の役割:
public class RealRole extends Nozzle{
//
public void role() {
System.out.println("RealRole!");
}
}
プロキシロール:
public class ProxyRole extends Nozzle {
//
//
private RealRole role ;
//
public void role() {
if(null == role){
role = new RealRole();
}
firstThing();// 。
role.role();// 。
secondThing();
}
public void firstThing(){
System.out.println(" !");
}
public void secondThing(){
System.out.println(" !");
}
}
テストクラス:
public class Test {
public static void main(String[] args) {
Nozzle role = new ProxyRole();
role.role();
}
}
印刷:
!
RealRole!
!
これは静的エージェントモードであり、静的エージェントモードには大きな弊害がある.このエージェントモードを使用すると、実際のロールは実装されなければならないため、エージェントオブジェクトの内部属性として使用され、実際のロールがエージェントロールに対応し、大量のリソースの浪費をもたらす.これによりダイナミックエージェントモードが作成されます.
動的プロキシ・モード:
JAvaダイナミックエージェントクラスはjava.lang.reflectパッケージの下にあります.主に2つのクラスの使用に関連しています.
1).Interface InvocationHandler:このインタフェースには1つのメソッドしか定義されていません
public Object invoke(Object obj,Method method,Object[] args)
実際の使用では、第1のパラメータobjは一般的に値エージェントクラスであり、第2のパラメータmethodは被エージェントの方法であり、第3のパラメータargs[]はこの方法のパラメータ配列を指す.この方法はエージェントクラスで動的に実装される.
2).Proxy:このクラスは動的エージェントクラスです.前例のProxyRoleのようなものです.
使用する方法:
protected Proxy(InvocationHandler h):内部のhに値を割り当てるための構造関数.
static Class getProxyClass(ClassLoader loader,Class[]interface):loaderはクラスローダであり、interfaceは実際のクラスが所有するすべてのインタフェースの配列であるエージェントクラスを取得します.
static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h):エージェントクラスのインスタンスを返し、返されたエージェントクラスをエージェントクラスとして使用できます.
動的エージェントクラス:
インタフェース:
public interface Subject {
public void request();
}
実際の役割:
public class RealSubject implements Subject{
public void request() {
System.out.println("From real subject!");
}
}
動的プロキシロール:
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject(Object obj){
this.sub = obj;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("brfore calling: "+method);
// RealSubject request() 。
method.invoke(sub,args);
System.out.println("after calling"+method);
return null;
}
}
テストクラス:
public class Client {
public static void main(String[] args) {
RealSubject r = new RealSubject();
InvocationHandler handler = new DynamicSubject(r);
Class<?> c = handler.getClass();
// , , Subject 。 。
Subject sub = (Subject)Proxy.newProxyInstance(c.getClassLoader(),r.getClass().getInterfaces(),handler);
// handler DynamicSubject invoke 。
sub.request();
}
}
このようにして,エージェントされたオブジェクト(RealSubject)を実行時に動的に変更することができ,制御が必要なインタフェース(Subjectインタフェース)を実行時に変更することができ,制御の方式(DynamicSubject)を動的に変更することができ,柔軟な動的代理モードを実現することができる.
動的エージェントクラス(Dynamic Proxy)とは、実行時に生成されたclassであり、生成時にinterfaceのセットを提供する必要があり、classはこれらのinterfaceを実現したと主張します.もちろん、このClassのインスタンスをこれらのinterfaceのいずれかとして使用することができます.もちろん、このDynamic Proxyは実はProxyで、それはあなたのために実質的な仕事をすることはありません.そのインスタンスを生成するときはhandlerを提供しなければなりません.それによって実際の仕事を引き継ぐ必要があります.
動的エージェント・モードの役割:ログとビジネスの分離、すなわちクラスが特定のビジネスを提供するだけであることを実現します.
動的エージェントの別の例:
public class VectorProxy implements InvocationHandler {
private Object proxyObj;
public VectorProxy(Object obj){
this.proxyObj = obj;
}
public static Object factory(Object obj){
Class<?> classType = obj.getClass();
return Proxy.newProxyInstance(classType.getClassLoader(),classType.getInterfaces(),new VectorProxy(obj));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before calling :"+method);
if(null != args){
for(Object o :args){
System.out.println(o);
}
}
Object object = method.invoke(proxyObj,args);
System.out.println("after calling :"+method);
return object;
}
public static void main(String[] args) {
List v = (List)factory(new Vector());
v.add("New");
v.add("York");
}
}
印刷:
before calling :public abstract boolean java.util.List.add(java.lang.Object)
New
after calling :public abstract boolean java.util.List.add(java.lang.Object)
before calling :public abstract boolean java.util.List.add(java.lang.Object)
York
after calling :public abstract boolean java.util.List.add(java.lang.Object)