今天來看一下什麼是代理設計模式,顧名思義,代理就是通過中介代替某人做某一件事,對應到我們的程式中就是通過代理物件來控制某個具體物件某個方法的訪問,在該方法之前和之後可以做一些額外處理。
- 概念理解
- 靜態代理
- 動態代理
概念理解#
- 抽象角色:用於定義真實角色和代理角色共有的方法。
- 真實角色:真實角色要實現的具體業務邏輯以供代理角色調用。
- 代理角色:用於代理真實角色,可在真實角色具體邏輯前後進行額外處理。
那麼代理的意義在於,當需要具體的業務邏輯時才調用真實角色的具體業務方法,即與真實角色具體業務邏輯無關的處理都放在代理類中的處理。
靜態代理#
先來看一下靜態代理的程式碼實現,定義抽象角色聲明共用的業務邏輯,具體如下:
/**
* 抽象角色
*/
public interface IBusiness {
/**
* 購物
*/
void buy();
}
然後,創建真實角色並完成具體的業務邏輯,具體如下:
/**
* 真實角色
*/
public class RealRole implements IBusiness{
@Override
public void buy() {
System.out.println("我要買東西");
}
}
然後,創建代理角色,在進行具體業務邏輯的時候必須調用真實角色的業務邏輯方法,具體如下:
/**
* 代理角色
*/
public class ProxyRole implements IBusiness{
private IBusiness mRealRole;
public ProxyRole(IBusiness realRole) {
this.mRealRole = realRole;
}
@Override
public void buy() {
//購買之前的額外評估
System.out.println("購買之前的額外評估...");
//具體的業務邏輯
mRealRole.buy();
//購買之後的滿意度調查
System.out.println("購買之後的滿意度調查...");
}
}
最後,使用剛才創建的相關靜態代理類,具體如下:
/**
* 測試靜態代理
*/
public class StaticClient {
public static void main(String[] args) {
//創建真實角色
IBusiness realRole = new RealRole();
//創建代理角色
IBusiness proxyRole = new ProxyRole(realRole);
//代購幫你買東西
proxyRole.buy();
}
}
測試效果如下:
購買之前的額外評估...
我要買東西
購買之後的滿意度調查...
這個案例中,代購不僅幫我們買到了東西,而且在購買行為發生之前和之後做了額外的處理,是不是比較非常靈活呢。
動態代理#
上面了解了靜態代理,那麼動態代理與靜態代理有什麼區別呢,實際上靜態代理和動態代理主要區別是靜態代理需要自己生成代理類,而動態代理是在程式碼運行過程中自動生成代理類,那麼動態代理如下實現呢,先來看一看 Java JDK 自帶的實現動態代理的關鍵的兩個類或介面,具體如下:
//用於動態生成代理類及其物件
java.lang.reflect.Proxy
//代理角色的調用處理程序需要實現的介面
//用於約束調用者的實現,抽象角色調用方法的時候會被該介面的invoke方法調用
java.lang.reflect.InvocationHandler
下面就來實現一下 Java JDK 自帶的動態代理,首先抽象角色和真實角色和上文中靜態代理的一樣,這裡就不在贅述,創建一個代理角色的調用處理程序如下:
/**
* 代理角色的調用處理程序
*/
public class BusinessHandler implements InvocationHandler{
private IBusiness mRealRole;
public BusinessHandler(IBusiness mRealRole) {
super();
this.mRealRole = mRealRole;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//購買之前的額外評估
System.out.println("購買之前的額外評估...");
//真實角色具體的業務邏輯
method.invoke(mRealRole, args);
//購買之後的滿意度調查
System.out.println("購買之後的滿意度調查...");
return null;
}
}
使用 Proxy 的靜態方法 newProxyInstance () 來生成代理物件,具體如下:
/**
* 測試JDK自帶的動態代理
*/
public class DynamicProxyClient {
public static void main(String[] args) {
//創建真實角色
IBusiness mRealRole = new RealRole();
//創建處理器介面
InvocationHandler handler = new BusinessHandler(mRealRole);
/**
* 獲取代理角色對應的代理物件
* newProxyInstance參數(類加載器,自動生成的代理類實現的介面,代理物件的調用處理程序)
*/
IBusiness proxy = (IBusiness) Proxy.newProxyInstance(handler.getClass().getClassLoader(), mRealRole.getClass().getInterfaces(), handler);
//代理角色幫你買東西
proxy.buy();
}
}
上述程式碼的執行結果如下:
購買之前的額外評估...
我要買東西
購買之後的滿意度調查...
學習靜態代理有助於對動態代理的學習,兩者主要的區別就是動態代理不需要寫代理類,其相應的代理類會在程式碼運行期間動態生成,當然生成的代理類也實現了抽象角色對應的介面,同時創建個代理角色的調用者處理程序 (InvocationHandler) 也會接管具體的業務邏輯。關於靜態代理和動態代理就到此為止。