代理模式(
Proxy Pattern
)也稱為委托模式。本質就是為某對象提供一種代理以控制對這個對象的訪問。
場景
很不幸你碰到了一個老板不給你發工資,你會請個律師幫你打官司。很顯然你對打官司一竅不通,因此只能通過代理對象去間接打官司。你作為委托對象,律師作為代理對象,都需要實現相同的接口或繼承相同的抽象類。
UML類圖
類圖.png
簡單實現
- 訴訟接口類
/**
* 訴訟接口類
*/
public interface ILawsuit {
//訴訟方法
void lawsuit();
}
- 訴訟人
/**
* 訴訟人(委托類)
*/
public class Person implements ILawsuit {
@Override
public void lawsuit() {
System.out.print("我要訴訟");
}
}
- 代理律師
/**
* 代理律師(代理對象)
*/
public class Laywer implements ILawsuit {
private ILawsuit mLawsuit; //持有被代理者的引用
public Laywer(ILawsuit lawsuit) {
this.mLawsuit = lawsuit;
}
@Override
public void lawsuit() {
mLawsuit.lawsuit();
}
}
- 客戶端調用
public void main(){
Person mPerson = new Person();
//構造一個代理律師,并將被代理者作為構造參數傳遞進去
ILawsuit iLawsuit = new Laywer(mPerson);
iLawsuit.lawsuit();
}
顯然,一個律師可以幫很多人打官司。其實我們這個代理類可以代理多個訴訟者,只要訴訟實現ILawsuit
接口,并將其作為構造參數傳遞進去。
代理模式大致分為兩種:一是靜態代理,二是動態代理。
上述示例即為靜態代理,代碼運行前代理類的class編譯文件已經存在了。而動態代理則相反,它是通過反射機制動態地生成代理對象。Java給我們提供了動態代理接口InvocationHandler,實現此接口需要重寫invoke方法。
延伸
AIDL類圖.png
回想《AIDL淺析》一文中類圖(如上),正是使用了代理模式。
IMyAidlInterface.Stub
作為委托類,IMyAidlInterface.Stub.Proxy
作為代理類,都實現了IMyAidlInterface
接口。而Stub
是個抽象類,并不處理過多的具體邏輯,真實的邏輯還是在RemoteService
中繼承了IMyAidlInterface.Stub
的子類MyBinder
里??蛻舳苏{用Stub.asInterface
方法將MyBinder
對象作為參數傳遞,返回一個AIDL
對象,執行add
方法。而真實的流程是,asInterface
方法首先會在本地查找AIDL
對象,如果沒有則實例化Proxy
,MyBinder
作為參數,執行add
方法。顯然Proxy
代理了Stub
的add
方法。
而追溯到底層,就需要了解Binder跨進程通信機制了。