本文參考《Android源碼設計模式解析與實戰(zhàn)第2版》
-
代理模式的定義
代理模式也稱為委托模式失暂,是為其他對象提供代理以控制這個對象的訪問暑始。
-
代理模式的使用場景
無法或不想直接訪問某個對象户盯,或者訪問某個對象困難時可以通過代理對象來實現(xiàn)間接訪問玖院。
-
代理模式的角色
- Subject:抽象主題-聲明真實主題和代理的共同接口方法(事情執(zhí)行步驟)
- RealSubject:真實主題類-該類表示所代理的真實對象(事情執(zhí)行步驟的具體實現(xiàn))
- ProxySubject:代理類-該類持有真實主題類的引用芜辕,在其所實現(xiàn)的接口方法中調(diào)用真實主題類中相應的接口方法執(zhí)行涧偷,以實現(xiàn)代理的目的
- Client:代理模式的執(zhí)行邏輯
-
代理模式的簡單實現(xiàn)
使用代理模式實現(xiàn)一個訴訟過程簸喂,律師極為代理
定義訴訟流程(抽象主題-Subject)可以是接口也可以是抽象方法
/**
* 抽象主題:
* 定義訴訟的流程
*/
interface ILawsuit {
/**
* 提交申請
*/
void submit();
/**
* 進行舉證
*/
void burden();
/**
* 開始辯護
*/
void defend();
/**
* 訴訟完成
*/
void finish();
}
定義具體對象(真實主題類-RealSubject),即被代理對象
/**
* 真實主題類:
* 被代理的真實對象燎潮,執(zhí)行步驟的具體實現(xiàn)
*/
class XiaoMin implements ILawsuit {
@Override
public void submit() {
System.out.println("申請仲裁喻鳄!");
}
@Override
public void burden() {
System.out.println("證據(jù)充足!");
}
@Override
public void defend() {
System.out.println("進行辯護确封!");
}
@Override
public void finish() {
System.out.println("訴訟成功除呵!");
}
}
定義代理律師(代理類-ProxySubject)代理類中需要持有真實對象的實現(xiàn),并且實現(xiàn)訴訟流程接口
/**
* 代理類
* 通過持有的真實對象和實現(xiàn)事件流程接口來實現(xiàn)代理功能
*/
class Lawyer implements ILawsuit{
private XiaoMin xiaoMin;//持有真實對象的引用
public Lawyer(XiaoMin xiaoMin) {
this.xiaoMin = xiaoMin;
}
@Override
public void submit() {
xiaoMin.submit();
}
@Override
public void burden() {
xiaoMin.burden();
}
@Override
public void defend() {
xiaoMin.defend();
}
@Override
public void finish() {
xiaoMin.finish();
}
}
定義代理模式的執(zhí)行邏輯(具體執(zhí)行-Client)
class Client {
public static void main(String[] args) {
initStaticProxy();
}
/**
* 靜態(tài)代理使用
*/
private static void initStaticProxy(){
//構建具體對象
XiaoMin xiaoMin = new XiaoMin();
//構造代理律師對象
ILawsuit lawyer = new Lawyer(xiaoMin);
//通過代理律師執(zhí)行具體訴訟邏輯
lawyer.submit();
lawyer.burden();
lawyer.defend();
lawyer.finish();
}
}
-
動態(tài)代理的實現(xiàn)
動態(tài)代理是通過實現(xiàn)InvocationHandler接口爪喘,反射調(diào)用被代理者方法颜曾,使得編譯階段不需要知道具體代理誰,運行時階段再確定代理誰秉剑,實現(xiàn)了代理類的復用泛豪。
動態(tài)代理類的具體實現(xiàn):
**
* 動態(tài)代理的實現(xiàn)
* 主要是實現(xiàn)InvocationHandler接口
* 通過invoke方法反射調(diào)用具體對象(被代理的對象)的方法
*/
class DynamicProxy implements InvocationHandler {
private Object obj;//被代理對象
public DynamicProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//調(diào)用被代理對象的方法
Object result = method.invoke(obj,args);
return result;
}
}
動態(tài)代理的具體使用:
class Client {
public static void main(String[] args) {
initDynamicProxy();
}
/**
* 動態(tài)代理的使用
*/
private static void initDynamicProxy(){
//構造具體對象
XiaoMin xiaoMin = new XiaoMin();
//構造動態(tài)代理
DynamicProxy dynamicProxy = new DynamicProxy(xiaoMin);
//獲取被代理類的classLoader
ClassLoader loader = xiaoMin.getClass().getClassLoader();
//構造具體的代理律師
ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader,new Class[]{ILawsuit.class},dynamicProxy);
//通過代理律師執(zhí)行具體訴訟邏輯
lawyer.submit();
lawyer.burden();
lawyer.defend();
lawyer.finish();
}
}
靜態(tài)代理和動態(tài)代理的區(qū)別:
本質(zhì)區(qū)別:靜態(tài)代理的代理者一般由程序員手動實現(xiàn),也就是編譯階段class的的編譯文件就已經(jīng)存在侦鹏,動態(tài)代理是通過反射機制動態(tài)地生成代理者對象诡曙,所以
編譯階段根本不知道代理誰,到底代理誰是在運行時階段決定略水。
具體區(qū)別:
1.動態(tài)代理代理對象不明確价卤,可以復用,一個代理類可以代理多個被代理類
2.動態(tài)代理通過反射調(diào)用被代理對象方法聚请,需要實現(xiàn)InvocationHandler接口
總結:
不論是靜態(tài)代理還是動態(tài)代理只是實現(xiàn)手法不同荠雕,其思想都是一致的稳其,簡單說就是:
真實對象的所有事物耿戚,全權交給代理對象去處理胆剧。