標籤:span add 相關資訊 應用 load 類圖 轉換 and instance
第十八章、代理模式
代理模式也稱託付模式,是結構型設計模式之中的一個。是應用廣泛的模式之中的一個。
1.定義
為其它對象提供一種代理以控制對這個對象的訪問。
2.使用情境
當無法或不想直接訪問某個對象或訪問某個對象存在困難時能夠通過一個代理對象來間接訪問,為了保證client使用的透明性。託付對象與代理對象須要實現相同的介面。
3.UML類圖
(1)Subject:抽象主題類。聲明真實主題與共同介面方法,該類能夠是抽象類別或介面。
(2)RealSubject:真實主題類(被託付類)。尤其運行詳細的商務邏輯方法。
(3)Proxy:代理類(託付類),該類持有一個對真實主題類的引用。在其所實現的介面方法中調用真實主題類中對應的介面方法運行,以此起到代理作用。
4.簡單實現
書中範例:以小民訴訟的流程舉例。那麼須要代理律師代理,訴訟簡單流程:提交申請–>進行舉證–>開始辯護–>訴訟完畢。
訴訟介面類:
public interface ILawsuit { /** * 提交申請 */ void submit(); /** * 進行舉證 */ void burden(); /** * 開始辯護 */ void defend(); /** * 訴訟完畢 */ void finish();}
詳細訴訟人小民:
public class XiaoMin implements ILawsuit{ @Override public void submit() { //小民申請仲裁 System.out.println("老闆年底拖欠工資。特此申請仲裁。"); } @Override public void burden() { //小民提交證據 System.out.println("這是合約書和過去一年的銀行工資流水!"); } @Override public void defend() { //鐵證如山 System.out.println("證據確鑿,不須要再說什麼!
"); } @Override public void finish() { //結果 System.out.println("訴訟成功。判決老闆即日起七天內結算工資!"); }}
代理律師:
public class Lawyer implements ILawsuit{ private ILawsuit mLawsuit; //持有一個詳細被代理者的引用 public Lawyer(ILawsuit lawsuit) { this.mLawsuit = lawsuit; } @Override public void submit() { mLawsuit.submit(); } @Override public void burden() { mLawsuit.burden(); } @Override public void defend() { mLawsuit.defend(); } @Override public void finish() { mLawsuit.finish(); }}
開始仲裁:
public class Client { public static void main(String[] args) { //構造出訴訟人小民 ILawsuit xiaomin = new XiaoMin(); //構造一個代理律師,並將小民傳遞進去 ILawsuit lawyer = new Lawyer(xiaomin); //律師提交申請 lawyer.submit(); //律師進行舉證 lawyer.burden(); //律師代小民辯護 lawyer.defend(); //完畢訴訟 lawyer.finish(); }}
結果:
老闆年底拖欠工資,特此申請仲裁!這是合約書和過去一年的銀行工資流水!證據確鑿,不須要再說什麼!訴訟成功,判決老闆即日起七天內結算工資!
相同我們也能夠代理其它人,僅僅須要實現ILawsuit就可以。上面的代理模式也叫靜態代理,也就是在代碼運行前代理類的class檔案就已經存在。
那麼相反。當然也會有動態代理,以下用動態代理實現上述範例:
Java提供了一個便捷的動態代理介面InvocationHandler。我們來實現它:
public class DynamicPorxy implements InvocationHandler{ private Object obj; //被代理類的引用 public DynamicPorxy(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 調用被代理類對象的方法 Object result = method.invoke(obj, args); return result; }}
這裡我們通過invoke方法來調用詳細的被代理方法。
改動後的Client類:
public class Client { public static void main(String[] args) { //構造出訴訟人小民 ILawsuit xiaomin = new XiaoMin(); //1.靜態代理 //構造一個代理律師。並將小民傳遞進去 //ILawsuit lawyer = new Lawyer(xiaomin); //-------------------------------------- //2.動態代理 //構造一個動態代理 DynamicPorxy proxy = new DynamicPorxy(xiaomin); //擷取被代理類小民的ClassLoader ClassLoader loader = xiaomin.getClass().getClassLoader(); //動態構造一個代理者律師 ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]{ ILawsuit.class }, proxy); //律師提交申請 lawyer.submit(); //律師進行舉證 lawyer.burden(); //律師代小民辯護 lawyer.defend(); //完畢訴訟 lawyer.finish(); }}
結果不變。由此能夠看出動態代理通過一個代理類來處理N多個被代理類,事實上質是對代理者與被代理者解耦。
相對而言靜態代理則僅僅能為給定介面下的實作類別做代理,假設介面不同那麼就須要又一次定義不同的代理類。較為複雜,可是靜態代理更符合物件導向原則。詳細使用哪種方式,依據個人喜好。
5.Android原始碼中的代理模式實現1.ActivityManagerProxy代理類
ActivityManager是Android中管理和維護Activity的相關資訊的類,為了隔離它與ActivityManagerService,有效減少二者的耦合,在這中間使用了ActivityManagerProxy代理類,全部對ActivityManagerService的訪問都轉換成對代理類的訪問,這樣ActivityManager就與ActivityManagerService解耦了。
6.總結1.長處
(1)對代理者與被代理者進行解耦。
(2)代理對象在client和目標對象之間起到一個中介的作用,這樣能夠起到對目標對象的保護。
2.缺點
基本沒有缺點,真要說缺點就是設計模式的通病:對類的添加。
《Android原始碼設計模式解析與實戰》讀書筆記(十八)