1.簡介
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。給目标對象提供一個代理對象,并由代理對象控制對目标對象的引用
2.靜态代理
2.1 概念
靜态代理在編譯時就已經實作,編譯完成後代理類是一個實際的class檔案。需要代理對象和目标對象實作一樣的接口。
- 優點:可以在不修改目标對象的前提下擴充目标對象的功能。
- 缺點:備援。由于代理對象要實作與目标對象一緻的接口,會産生過多的代理類。不易維護。一旦接口增加方法,目标對象與代理對象都要進行修改。
2.2案例
public interface ITask {
void dispatchTask();
}
/**
* 老闆
*/
public class Boss implements ITask {
private static final String TAG = "Boss";
@Override
public void dispatchTask() {
Log.d(TAG, "dispatchTask: ");
}
}
/**
* 秘書
*/
public class Secretary implements ITask {
Boss realObj;
public Secretary( Boss realObj) {
this.realObj = realObj;
}
@Override
public void dispatchTask() {
}
}
調用
Boss boss = new Boss();
final Secretary proxyObj = new Secretary(boss);
proxyObj.dispatchTask();
3.動态代理
動态代理對象不需要實作接口,但是要求目标對象必須實作接口,否則不能使用動态代理。
JDK提供了代理對象:
- java.lang.reflect Proxy,主要方法為
static Object newProxyInstance(
ClassLoader loader, //指定目前目标對象的類加載器
Class<?>[] interfaces, //目标對象實作的接口的類型
InvocationHandler h //事件處理器
)
//傳回一個指定接口的代理類執行個體,該接口可以将方法調用指派到指定的調用處理程式。
- java.lang.reflect InvocationHandler,主要方法為
Object invoke(Object proxy, Method method, Object[] args)
// 在代理執行個體上處理方法調用并傳回結果。
3.1 案例
public interface IUserDao {
void save();
}
public class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("儲存資料");
}
}
public class ProxyFactory {
private Object target;// 維護一個目标對象
public ProxyFactory(Object target) {
this.target = target;
}
// 為目标對象生成代理對象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開啟事務");
// 執行目标對象方法
Object returnValue = method.invoke(target, args);
System.out.println("送出事務");
return null;
}
});
}
}
IUserDao target = new UserDao();
System.out.println(target.getClass()); //輸出目标對象資訊
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.println(proxy.getClass()); //輸出代理對象資訊
proxy.save(); //執行代理方法