意図
他のオブジェクトへのアクセスを制御します。
クラス図
抽象的役割:実オブジェクトとプロキシオブジェクトの共通インターフェースを宣言して、実オブジェクトが使用されている場所ならどこでもプロキシオブジェクトを使用できるようにします。
エージェントの役割:エージェントオブジェクトには実オブジェクトへの参照が含まれているため、実オブジェクトはいつでも操作できます。プロキシオブジェクトと実オブジェクトは同じインターフェイスを持っているため、いつでも実オブジェクトを置き換えることができます。プロキシオブジェクトは通常、実オブジェクトの操作の前後に他の操作を追加します。これは、実オブジェクトをカプセル化することと同じです。
実際の役割:つまり、プロキシオブジェクトが表す実際のオブジェクトであり、最終的に参照したいオブジェクトです。
実装
// 抽象角色
interface Subject{
public void doSomething();
}
// 目标角色
class RealSubject implements Subject{
public void doSomething() {
System.out.println("call doSomething()");
}
}
// 代理角色
class SubjectProxy implements Subject{
// 代理持有目标对象的引用
Subject subimpl = new RealSubject();
public void doSomething() {
System.out.println("before"); //调用目标对象之前可以做相关操作
subimpl.doSomething();
System.out.println("after");//调用目标对象之后可以做相关操作
}
}
public class Test {
public static void main(String[] args) throws Exception {
Subject sub = new SubjectProxy();
sub.doSomething();
}
}
既存の問題:
1. RealSubjectが将来新しいインターフェースを実装する必要がある場合、プロキシクラスにインターフェースの実装メソッドを記述する必要があり、プロキシクラスのコードが肥大化する原因になります
2.抽象ロールインターフェイスを変更する必要がある場合は、間違いなく、実際のロールとエージェントロールも変更する必要があります。
JDK動的プロキシ
package com.eastern.msap.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Subject {
public void doSomething();
}
class RealSubject implements Subject {
public void doSomething() {
System.out.println("call doSomething()");
}
}
class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),// 绑定该类实现的所有接口,取得代理类
this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("在调用具体函数方法前,执行功能处理");
result = method.invoke(target, args);
System.out.println("在调用具体函数方法后,执行功能处理");
return result;
}
}
public class Test {
public static void main(String args[]) {
ProxyHandler proxyHandler = new ProxyHandler(new RealSubject());
Subject sub = (Subject) proxyHandler.getProxyInstance();
sub.doSomething();
}
}
在调用具体函数方法前,执行功能处理
call doSomething()
在调用具体函数方法后,执行功能处理
質問1の場合、JDK動的プロキシはターゲットオブジェクトによって実装されたすべてのインターフェイスに基づいてプロキシクラスオブジェクトを生成するため、ターゲットオブジェクトが新しいインターフェイスを実装する必要がある場合、プロキシクラスを生成するコードを変更する必要はありません。
2番目の質問については、インターフェースが変更された場合、[プロキシクラス]を変更する必要がありますが、プロキシクラスを生成するコードを変更する必要はありません。
この呼び出しは十分な柔軟性がありますが、特定のインターフェイスを実装するプロキシクラスを明示的に作成する代わりに、特定のプロキシクラスを動的に生成できます。