JAva設計モード--エージェントモード


プロキシ・モード定義:
オブジェクトへのアクセスを制御するプロキシを提供します.
役割の分類:
1、Subject抽象テーマロール抽象テーマクラスは抽象クラスでもインタフェースでもよく、最も一般的なビジネスタイプ定義であり、特別な要求はない.
2、RealSubjectの具体的なテーマの役、委託された役、代理された役.Subjectインタフェースを実現することは、ビジネスロジックの具体的な実行者である.
3、Proxy  エージェント・トピック・ロール.委任クラス、エージェントクラスです.実際のロールへの応用を担当し、すべての抽象的なトピッククラス定義の方法制限を実際のトピックロールに委任して実現し、実際のトピックロールの処理が完了する前に前処理と後処理を行います.
主に三つの部分に分かれている
1、静的エージェント
2、ダイナミックエージェント(JDK、CGLIB以降)
3、JDK動的代理原理
シミュレーションシーン:スターに電話すると、アシスタントが出るのが普通です.まず、電話インタフェースと実装クラスを定義します.
/**
 *      
 */
public interface AnswerSubject {

    /**
     *    
     * @param name      
     */
    void answer(String name);
}


/**
 *    
 */
public class RealAnswerSubject implements AnswerSubject {

    @Override
    public void answer(String name) {
        System.out.println("  ,  "+name+"   。");
    }
    
}

1、静的エージェント
はっきり言ってエージェントクラスnewが出てきて、静的で、エージェントクラスがそのクラスであることを知っています.
1.1静的エージェント
/**
 *        
 */
public class AnswerProxy implements AnswerSubject {

    /**
     *      
     */
    private AnswerSubject answerSubject;

    public AnswerProxy(AnswerSubject answerSubject) {
        this.answerSubject = answerSubject;
    }

    @Override
    public void answer(String name) {
        /**
         *                 
         */
        answerSubject.answer(name);
    }
}
テスト:既知のエージェントクラスオブジェクトを直接newし、すべて静的エージェントです.
public static void main(String[] args) {

	//   new       
	AnswerProxy answerProxy = new AnswerProxy(new RealAnswerSubject());
	
	answerProxy.answer("   ");
}

1.2静的エージェント変種の一般的なエージェントは、スターに直接電話することはできません.まずアシスタントを通過しなければなりません.すなわち,被エージェントオブジェクトはエージェントのみでアクセスでき,直接被エージェントオブジェクトにアクセスできない.クラスの改造を実現する:
public class RealAnswerSubject implements AnswerSubject {

    public RealAnswerSubject(AnswerProxy proxy) {
        //    ,   new,      
        if(proxy==null){
            throw  new RuntimeException("    ");
        }
    }
    @Override
    public void answer(String name) {
        System.out.println("  ,  "+name+"   。");
    } 
}

エージェントオブジェクトの変更:
/**
 *      
 */
public class AnswerProxy implements AnswerSubject {

    /**
     *      
     */
    private AnswerSubject answerSubject;

    public AnswerProxy() {
        //       ,       
        this.answerSubject = new RealAnswerSubject(this);
    }

    @Override
    public void answer(String name) {
        /**
         *                 
         */
        answerSubject.answer(name);
    }
}

テストクラス:このときエージェントオブジェクトを直接使用し、newエージェントオブジェクトを使用しなくても、エージェントオブジェクトが外部に露出しなくても、エージェントされているのは誰なのか分かりません.
public static void main(String[] args) {

	//   new       
	AnswerProxy answerProxy = new AnswerProxy();

	answerProxy.answer("   ");

}

1.3静的エージェント変種の強制エージェント
スターとよく知っているかもしれませんが、スターに電話すると、スターは私のアシスタントを探していると言っています.私のアシスタントは知っています.
つまり、エージェントを迂回して直接被エージェントにアクセスしたいのですが、被エージェント(スター)はまたエージェント(アシスタント)に戻ります.実際のロールからエージェントロールを検索します.そうしないとアクセスできません.
インタフェースの変更:
/**
 *      
 */
public interface AnswerSubject {

    /**
     *    
     * @param name      
     */
    void answer(String name);

    /**
     *              
     * @return
     */
    AnswerSubject getProxy();
}

クラスの改造を実現する:
/**
 *    
 */
public class RealAnswerSubject implements AnswerSubject {

    //  
    private AnswerProxy answerProxy;

    @Override
    public AnswerSubject getProxy() {
        //      ,          
        answerProxy = new AnswerProxy(this);
        return answerProxy;
    }

    @Override
    public void answer(String name) {
        //      ,    
        if(answerProxy==null){
            throw new RuntimeException("      ");
        }
        System.out.println("  ,  "+name+"   。");
    }
    
}

エージェントクラスの変更:
/**
 *      
 */
public class AnswerProxy implements AnswerSubject {

    /**
     *      
     */
    private AnswerSubject answerSubject;

    /**
     * @param answerSubject       
     */
    public AnswerProxy(AnswerSubject answerSubject) {
        this.answerSubject = answerSubject;
    }

    @Override
    public void answer(String name) {
        answerSubject.answer(name);
    }

    @Override
    public AnswerSubject getProxy() {
        //           
        return this;
    }
}

≪テスト|Test|emdw≫:プロキシ・オブジェクトを取得し、プロキシ・オブジェクトからアクセスする必要があります.この方法では,エージェントオブジェクトは実オブジェクトで制御され,外部には実オブジェクトによって実オブジェクトを取得したエージェントオブジェクトのみがアクセスできる.
public static void main(String[] args) {

	//   new       
	AnswerSubject answerSubject = new RealAnswerSubject();

	//      
	//answerSubject.answer("   ");

	//      ,          
	AnswerSubject proxy = answerSubject.getProxy();
	proxy.answer("   ");

}

1.4静的エージェント拡張
スターに電話して、この前はアシスタントが迎えに来たので、スターが忙しいと言っていました.3回目のスターを打ってやっと迎えた.これで電話をかけた回数を記録する拡張が必要です.この記録方法は、電話をかけるたびに呼び出され、エージェントは、処理方法の前または後に呼び出されるインタフェースを実装する.
2、ダイナミックエージェント
/**
 *      
 */
public interface AnswerSubject {
    /**
     *    
     * @param name      
     */
    void answer(String name);

}
/**
 *    
 */
public class RealAnswerSubject implements AnswerSubject {
    @Override
    public void answer(String name) {
        System.out.println("  ,  "+name+"   。");
    }
}	

JDKのインタフェースInvocationHandlerは、このインタフェースを実現し、プロキシオブジェクトメソッドによってプロキシされる
/**
 *            
 */
public class AnswerHandler implements InvocationHandler {

    /**
     *      
     */
    private Object target;

    public AnswerHandler(Object target) {
        this.target = target;
    }
	
    /**
     *                                
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //    
        Object result = method.invoke(target, args);
        return result;
    }
}

テスト:
public static void main(String[] args)  throws Exception{

	//     
	RealAnswerSubject answerSubject = new RealAnswerSubject();

	//     handler
	InvocationHandler handler = new AnswerHandler(answerSubject);

	ClassLoader loader = answerSubject.getClass().getClassLoader();

	//        
	AnswerSubject proxy = (AnswerSubject)Proxy.newProxyInstance(loader, new Class[]{AnswerSubject.class}, handler);

	proxy.answer("   ");

}

JDK Proxy.newProxyInstance()経由  メソッドは、被エージェントオブジェクトインタフェースのすべてのメソッドを実現するエージェントオブジェクトを生成します.
エージェントオブジェクトは、InvocationHandlerインタフェースを介して行われ、すべてのメソッドはHandlerによって処理されます.すなわち、すべての被エージェントメソッドはInvocationHandlerによって実際の処理タスクを引き継ぎます.
3、JDK動的代理原理
被エージェントクラスのすべてのインタフェースを実装し,バイトコードファイルを生成してエージェントオブジェクトを構築し,反射構造被エージェントクラスのインスタンスを保持し,invoke反射により被エージェントクラスインスタンスを呼び出す方法によりエージェントを実現する. 
ソース分析 https://blog.csdn.net/convict_eva/article/details/80239838