設計パターンのまとめ(Java):エージェントパターン(静的エージェントと動的エージェント)
4412 ワード
一、静的エージェント
1.1静的エージェント
プログラマによって作成または特定のツールによって自動的にソースコードを生成し、コンパイルします.プログラムが実行される前に、エージェントクラスの.classファイルはすでに存在します.
1.2事件列
インタフェースクラス:
実装クラス:
エージェントクラス:
テストクラス:
静的エージェントのメリットとデメリット:
利点:ビジネスクラスはビジネスロジック自体に注目するだけで、ビジネスクラスの再利用性を保証します.これはエージェントの共通の利点です.欠点:1)エージェントオブジェクトの1つのインタフェースは1つのタイプのオブジェクトにのみサービスし,エージェントする方法が多い場合は,各メソッドにエージェントを行う必要があり,静的エージェントはプログラム規模がやや大きい場合には適任ではない.
2)インタフェースにメソッドが追加された場合,すべての実装クラスがこのメソッドを実装する必要があるほか,すべてのエージェントクラスもこのメソッドを実装する必要がある.コードメンテナンスの複雑さが増しました.
また、上記の方法でエージェントモードを使用する場合は、実際のロール(委任クラス)は事前に存在し、エージェントオブジェクトの内部属性として使用する必要があります.しかし、実際に使用する場合、実際のロールはエージェントロールに対応する必要があります.大量に使用すると、クラスが急激に膨張します.また,実際のキャラクタ(委任クラス)が事前に知られていなかった場合,エージェントをどのように使用するか.この問題はJavaの動的エージェントクラスで解決できる.
二、動的代理
2.1動的エージェントとは
動的エージェントクラスのソースコードは,プログラム実行中にJVMによって反射などのメカニズムに従って動的に生成されるため,エージェントクラスのバイトコードファイルは存在しない.エージェントクラスと委任クラスの関係は、プログラムの実行時に決定されます.
2.2 JDK動的エージェント
JDK動的エージェントが使用するエージェントクラスは、プログラムによってエージェントクラスオブジェクトに呼び出されたときにJVMによって実際に作成されます.JVMは、転送されたビジネス実装クラスオブジェクトおよびメソッド名に基づいて、エージェントクラスのclassファイルを動的に作成し、バイトコードエンジンによって実行され、そのエージェントクラスオブジェクトによってメソッド呼び出しが行われます.エージェントクラスの前処理、呼び出し後の操作を指定するだけで実行できます.
ケース列
インタフェースクラスと実装クラスは、上の静的エージェントと同じです.
エージェントクラス:
JDKダイナミックエージェントのエージェントオブジェクトは、作成時に、ビジネスインプリメンテーションクラスで実装されるインタフェースをパラメータとして使用する必要があります(後のエージェントメソッドではインタフェース内のメソッド名に従って呼び出す必要があるため).ビジネスインプリメンテーションクラスがインプリメンテーションインタフェースを持たずにビジネスメソッドを直接定義している場合,JDKダイナミックエージェントは使用できない.また、ビジネスインプリメンテーションクラスにインタフェースにないメソッドが追加された場合、これらのメソッドはエージェントされません(呼び出せないため).
2.3 cglibダイナミックエージェント
cglibはクラスに対してエージェントを実装し、指定したビジネスクラスに対してサブクラスを生成し、その中のビジネスメソッド実装エージェントを上書きする原理である.継承を採用しているためfinal修飾のクラスをエージェントすることはできない.
まずビジネスクラスを定義し、インタフェースを実装する必要はありません(もちろん、インタフェースを実装しても構いませんが、影響しません)
エージェントクラス:
2.4.両者の長所と短所の分析はJDKダイナミックエージェントを使用して、目標クラスが実現しなければならないあるインタフェース、あるクラスが実現インタフェースがなければエージェントオブジェクトを生成できない.
Cglibの原理は,ターゲットクラスに対してサブクラスを生成し,その中のすべてのメソッドを上書きするため,ターゲットクラスとメソッドをfinalタイプとして宣言することはできない.
実行効率の点からCglib動的エージェントの方が効率的である.
1.1静的エージェント
プログラマによって作成または特定のツールによって自動的にソースコードを生成し、コンパイルします.プログラムが実行される前に、エージェントクラスの.classファイルはすでに存在します.
1.2事件列
インタフェースクラス:
public interface Subject {
public void play();
}
実装クラス:
public class RealSubject implements Subject{
public void play() {
System.out.println(" !");
}
}
エージェントクラス:
public class ProxySubject implements Subject{
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
public void play() {
subject.play();
}
}
テストクラス:
public class Test {
public static void main(String[] args) {
ProxySubject subject = new ProxySubject(new RealSubject());
subject.play();
}
}
静的エージェントのメリットとデメリット:
利点:ビジネスクラスはビジネスロジック自体に注目するだけで、ビジネスクラスの再利用性を保証します.これはエージェントの共通の利点です.欠点:1)エージェントオブジェクトの1つのインタフェースは1つのタイプのオブジェクトにのみサービスし,エージェントする方法が多い場合は,各メソッドにエージェントを行う必要があり,静的エージェントはプログラム規模がやや大きい場合には適任ではない.
2)インタフェースにメソッドが追加された場合,すべての実装クラスがこのメソッドを実装する必要があるほか,すべてのエージェントクラスもこのメソッドを実装する必要がある.コードメンテナンスの複雑さが増しました.
また、上記の方法でエージェントモードを使用する場合は、実際のロール(委任クラス)は事前に存在し、エージェントオブジェクトの内部属性として使用する必要があります.しかし、実際に使用する場合、実際のロールはエージェントロールに対応する必要があります.大量に使用すると、クラスが急激に膨張します.また,実際のキャラクタ(委任クラス)が事前に知られていなかった場合,エージェントをどのように使用するか.この問題はJavaの動的エージェントクラスで解決できる.
二、動的代理
2.1動的エージェントとは
動的エージェントクラスのソースコードは,プログラム実行中にJVMによって反射などのメカニズムに従って動的に生成されるため,エージェントクラスのバイトコードファイルは存在しない.エージェントクラスと委任クラスの関係は、プログラムの実行時に決定されます.
2.2 JDK動的エージェント
JDK動的エージェントが使用するエージェントクラスは、プログラムによってエージェントクラスオブジェクトに呼び出されたときにJVMによって実際に作成されます.JVMは、転送されたビジネス実装クラスオブジェクトおよびメソッド名に基づいて、エージェントクラスのclassファイルを動的に作成し、バイトコードエンジンによって実行され、そのエージェントクラスオブジェクトによってメソッド呼び出しが行われます.エージェントクラスの前処理、呼び出し後の操作を指定するだけで実行できます.
ケース列
インタフェースクラスと実装クラスは、上の静的エージェントと同じです.
エージェントクラス:
public class ProxySubject {
private static void before() {
System.out.println(" !");
}
private static void after() {
System.out.println(" ");
}
public static void main(String[] args) {
final Subject subject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object object = method.invoke(subject, args);
after();
return object;
}
});
proxy.play();
}
}
JDKダイナミックエージェントのエージェントオブジェクトは、作成時に、ビジネスインプリメンテーションクラスで実装されるインタフェースをパラメータとして使用する必要があります(後のエージェントメソッドではインタフェース内のメソッド名に従って呼び出す必要があるため).ビジネスインプリメンテーションクラスがインプリメンテーションインタフェースを持たずにビジネスメソッドを直接定義している場合,JDKダイナミックエージェントは使用できない.また、ビジネスインプリメンテーションクラスにインタフェースにないメソッドが追加された場合、これらのメソッドはエージェントされません(呼び出せないため).
2.3 cglibダイナミックエージェント
cglibはクラスに対してエージェントを実装し、指定したビジネスクラスに対してサブクラスを生成し、その中のビジネスメソッド実装エージェントを上書きする原理である.継承を採用しているためfinal修飾のクラスをエージェントすることはできない.
まずビジネスクラスを定義し、インタフェースを実装する必要はありません(もちろん、インタフェースを実装しても構いませんが、影響しません)
public class BookFacadeImpl {
public void addBook() {
System.out.println(" ...");
}
}
エージェントクラス:
public class BookFacadeCglib implements MethodInterceptor {
// JDK
public Object getInstance(Class clazz) {
Enhancer enhancer = new Enhancer(); // ,
enhancer.setSuperclass(clazz); // ( : )
// : , CallBack, Callback intercept()
enhancer.setCallback(this);
//
return enhancer.create();
}
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(" ——————");
Object obj = proxy.invokeSuper(object, args); // ( )
System.out.println(" ——————");
return obj;
}
public static void main(String[] args) {
BookFacadeCglib cglib = new BookFacadeCglib();
BookFacadeImpl proxy = (BookFacadeImpl) cglib.getInstance(BookFacadeImpl.class);
proxy.addBook();
}
}
2.4.両者の長所と短所の分析はJDKダイナミックエージェントを使用して、目標クラスが実現しなければならないあるインタフェース、あるクラスが実現インタフェースがなければエージェントオブジェクトを生成できない.
Cglibの原理は,ターゲットクラスに対してサブクラスを生成し,その中のすべてのメソッドを上書きするため,ターゲットクラスとメソッドをfinalタイプとして宣言することはできない.
実行効率の点からCglib動的エージェントの方が効率的である.