java proxy model


≪プロキシ・モード|Proxy Mode|ldap≫:このオブジェクトへのアクセスを制御するために他のオブジェクトにプロキシを提供します.
1つのclientは別のオブジェクトを直接参照したくないが、エージェントオブジェクトはclientとserverの間で仲介の役割を果たすことができる.
抽象ロール:リアルオブジェクトとエージェントオブジェクトの共通インタフェースを宣言します.
≪プロキシ・ロール|Proxy Roles|ldap≫:プロキシ・オブジェクト・ロールには、リアル・オブジェクトを操作できるリファレンスが含まれています.また、プロキシ・オブジェクトは、リアル・オブジェクトと同じインタフェースを提供し、リアル・オブジェクトの代わりにいつでも使用できます.また、プロキシオブジェクトは、実際のオブジェクト操作を実行するときに、実際のオブジェクトをカプセル化することに相当する他の操作を追加することができます.
≪リアル・ロール|Real Role|emdw≫:エージェント・ロールが表すリアル・オブジェクトは、最終的に参照するオブジェクトです.

    : 

abstract   public   class  Subject  {
    abstract   public   void  request(); 
}  

    :   Subject request()  。 

 public   class  RealSubject  extends  Subject  { 
     public  RealSubject()  { }  
    
     public   void  request()  { 
        System.out.println( " From real subject. " ); 
    }  
}  


    : 

 public   class  ProxySubject  extends  Subject  { 
     private  RealSubject realSubject;  //                 
 
      public  ProxySubject()  { }  


     public   void  request()  {  //            request    
         preRequest(); 

         if ( realSubject  ==   null  )  { 

            realSubject  =   new  RealSubject(); 
        }  

        realSubject.request();  //          request    
 
        postRequest(); 
    } 


      : 

Subject sub = new  ProxySubject(); 
Sub.request(); 


上記の方法でプロキシモードを使用する場合は、実際のロールは事前に存在し、プロキシオブジェクトの内部プロパティとして使用する必要があります.しかし、実際に使用する場合、実際のロールはエージェントロールに対応する必要があります.大量に使用すると、クラスが急激に膨張します.また、実際のロールが事前に知られていない場合は、エージェントをどのように使用すればいいのでしょうか.この問題はJavaの動的エージェントクラスで解決できる.
===================================================================
JavaダイナミックエージェントクラスはJavaにある.lang.reflectパッケージ
(1). Interface InvocationHandler:このインタフェースには、メソッドObject:invoke(Object obj,Method method,Object[]args)が1つだけ定義されています.実際に使用する場合、最初のパラメータobjは一般的にエージェントクラスを指し、methodは前例のrequest()のようなエージェントされるメソッドであり、argsはこのメソッドのパラメータ配列である.この抽象的な方法はエージェントクラスで動的に実現される.
(2).Proxy:このクラスは動的エージェントクラスであり、前例のProxySubjectと同様の役割を果たします.主に以下の内容が含まれています.
Protected Proxy(InvocationHandler h):内部のhに値を割り当てる関数を構築します.
Static Class getProxyClass(ClassLoader loader,Class[]interfaces):loaderはクラスローダであり、interfacesは実際のクラスが所有するすべてのインタフェースの配列であるエージェントクラスを取得します.
Static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h):エージェントクラスのインスタンスを返し、返されたエージェントクラスを被エージェントクラスとして使用できます(Subjectインタフェースで宣言されたメソッドを使用できます).
Dynamic Proxyとは、実行時に生成されたclassであり、生成時にinterfaceのセットを提供する必要があり、classはこれらのinterfaceを実現したと主張します.もちろんclassのインスタンスをこれらのinterfaceのいずれかとして使用することができます.もちろん、このDynamic Proxyは実際にはProxyであり、実質的な仕事をすることはありません.インスタンスを生成するときはhandlerを提供し、実際の仕事を引き継ぐ必要があります.

    (      ,       ): 

 public   interface  Subject  { 
    abstract   public   void  request(); 
}  



    RealSubject:
 public   class  RealSubject  implements  Subject {

   public  RealSubject() {} 
 
    public   void  request() {
    System.out.println( " From real subject. " );
  } 
 
}  

     : 

 import  java.lang.reflect.Method;

 import  java.lang.reflect.InvocationHandler;

 public   class  DynamicSubject  implements  InvocationHandler  {
   private  Object sub;
   public  DynamicSubject()  {} 
 
    public  DynamicSubject(Object obj)  {
    sub  =  obj;
  } 
 
 public  Object invoke(Object proxy, Method method, Object[] args)  throws  Throwable  {
   System.out.println( " before calling  "   +  method);
   method.invoke(sub,args);

   System.out.println( " after calling  "   +  method);
    return   null ;
 } 
 
} 
          Object ,              DynamicSubject(Object obj)    ;

       invoke  ,     method.invoke(sub,args);

                    ,    sub         ,args                 。       ,                    。

import  java.lang.reflect.InvocationHandler; 
 import  java.lang.reflect.Proxy; 
 import  java.lang.reflect.Constructor; 
 import  java.lang.reflect.Method; 

 public   class  Client  { 

 static   public   void  main(String[] args)  throws  Throwable  { 

   RealSubject rs  =   new  RealSubject();  //            
    InvocationHandler ds  =   new  DynamicSubject(rs); 
   Class cls  =  rs.getClass(); 

    //            
    Subject subject  =  (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds ); 
   subject.request(); 

}  


      :
before calling public abstract void Subject.request()
From real subject.
after calling public abstract void Subject.request()