代理模式也叫委託模式,是一種結構型設計模式。爲其他對象提供一種代理,以控制對這個對象的訪問。那麼什麼時候使用代理模式呢?當無法或者不想直接訪問某個對象時,或者訪問某個對象有困難時,可以通過一個代理對象來間接訪問,爲了保證客戶端使用的透明性,委託對象與代理對象需要實現相同的接口。
1 創建一個共同的接口
package proxypattern;
public abstract class Subject {
/**普通的業務方法*/
public abstract void visit();
}
2 創建一個真實對象的類
package proxypattern;
public class RealSubject extends Subject{
@Override
public void visit() {
//實現具體邏輯
System.out.println("RealSubject---");
}
}
3 創建一個代理類,在其中聲明真實主題類型的變量
package proxypattern;
public class ProxySubject extends Subject{
private RealSubject mSubject;
public ProxySubject(RealSubject mSubject) {
super();
this.mSubject = mSubject;
}
@Override
public void visit() {
//通過真實主題引用的對象,調用真實主題中的邏輯方法
mSubject.visit();
}
}
4 通過代理類調用真實主題的對象
package proxypattern;
public class Client {
public static void main(String[] args) {
//構造真實主題的對象
RealSubject realSubject = new RealSubject();
//通過真實主題對象構造一個代理對象
ProxySubject proxySubject = new ProxySubject(realSubject);
//調用代理對象的方法,間接調用真實主題的業務邏輯
proxySubject.visit();
}
}
輸出結果:RealSubject--Method----
以上的代理模式爲靜態代理模式,就是代理類所代理的對象的類型是固定的;此外,我們還可以更加靈活地處理被代理對象的類型,這是動態代理模式:
首先創建一個動態代理類:
package proxypattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 動態代理類
*/
public class DynamicProxy implements InvocationHandler{
//被代理的類 的引用
private Object object;
/**
* 在構造方法中初始化引用對象
* @param object
*/
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//調用被代理對象的方法
Object invoke = method.invoke(object, args);
return invoke;
}
}
通過Java中的Proxy類,獲取一個RealSubject實現的接口類型一致的代理類,再通過這個代理類調用被代理對象的方法:
package proxypattern;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
//1 構造一個被代理對象
Subject subject = new RealSubject();
//2 獲取被代理類的ClassLoader
ClassLoader loader = subject.getClass().getClassLoader();
//3 構造一個動態代理
DynamicProxy proxy = new DynamicProxy(subject);
//4 通過loader構造一個代理對象
Subject proxyInstance = (Subject) Proxy.newProxyInstance(loader, new Class[]{Subject.class}, proxy);
//5 代理對象調用被代理對象的方法
proxyInstance.visit();
}
}
輸出結果:RealSubject--Method----