Android中的代理(Proxy)模式
一. Proxy模式定義
Proxy模式,也稱代理模式,是經典設計模式中的一種結構型模式,其定義是為其他對象提供一種代理以控制對這個對象的訪問,簡單的說就是在訪問和被訪問對象中間加上的一個間接層,以隔離訪問者和被訪問者的實現細節。
二. Proxy模式理解
當無法或者不想直接訪問某個對象, 或者訪問某個對象存在困難時, 可以通過一個代理對象來間接訪問,
為了保證客戶端使用的透明性, 委托對象與代理對象需要實現相同的接口。
例如,ActivityManager 作為客戶端要訪問 AMS,AMS 不希望直接暴露在客戶端面前,或者不想被客戶端的某些操作影響到自己內部結構,
就暴露出一個代理對象ActivityManagerProxy,讓ActivityManagerProxy參與客戶端與服務端的交互,這樣就完美了。
三. Proxy模式應用場景
重點在於AIDL的使用。
四. Proxy模式的分類
1.虛代理( Remote Proxy ):代理一些開銷很大的對象,這樣便能迅速返回,進行其它操作,只有在真正需要時才實例化;
2.遠程代理( Remote Proxy ): 為一個對象在不同的地址空間提供局部代表。
3.保護代理(Protection Proxy):控制對原始對象的訪問。保護代理用於對象應該有不同的訪問權限的時候。
4. 智能指引(Smart Reference): 取代了簡單的指針,它在訪問對象時執行一些附加操作。
- 當客戶端對象需要訪問遠程主機中的對象時可以使用遠程代理。
- 當需要用一個消耗資源較少的對象來代表一個消耗資源較多的對象,從而降低系統開銷、縮短運行時間時可以使用虛擬代理,例如一個對象需要很長時間才能完成加載時。
- 當需要為某一個被頻繁訪問的操作結果提供一個臨時存儲空間,以供多個客戶端共享訪問這些結果時可以使用緩沖代理。
- 通過使用緩沖代理,系統無須在客戶端每一次訪問時都重新執行操作,只需直接從臨時緩沖區獲取操作結果即可。
- 當需要控制對一個對象的訪問,為不同用戶提供不同級別的訪問權限時可以使用保護代理。
- 當需要為一個對象的訪問(引用)提供一些額外的操作時可以使用智能引用代理。
五. Proxy模式的優缺點
六. Proxy模式Demo解析
代理模式類型圖:
在代理模式中的角色:
● 抽象對象角色:聲明了目標對象和代理對象的共同接口,這樣一來在任何可以使用目標對象的地方都可以使用代理對象。
● 目標對象角色:定義了代理對象所代表的目標對象。
● 代理對象角色:代理對象內部含有目標對象的引用,從而可以在任何時候操作目標對象;代理對象提供一個與目標對象相同的接口,以便可以在任何時候替代目標對象。 代理對象通常在客戶端調用傳遞給目標對象之前或之後,執行某個操作,而不是單純地將調用傳遞給目標對象。
下面附上代碼:
公共接口:
1 public interface InterObject { 2 public abstract void doEexc(); 3 }
目標對象角色:
1 public class RealObject implements InterObject { 2 @Override 3 public void //執行的操作 4 System.out.println("執行操作"); 5 } 6 }
代理對象角色:
1 public class ProxyObject new RealObject(); 2 @Override 3 public void //調用目標對象之前可以做相關操作 4 System.out.println("before"); 5 realObject.doEexc(); 6 //調用目標對象之後可以做相關操作 7 System.out.println("after"); 8 } 9 }
Client:
1 public class Client { 2 public static void main(String[] args) { 3 // TODO Auto-generated method stub 4 RealObject rel = new RealObject(); 5 InterObject obj = new ProxyObject(); 6 obj.doEexc(); 7 } 8 }
執行結果:
before
執行操作
after
從上面的例子可以看出代理對象將客戶端的調用委派給目標對象,在調用目標對象的方法之前跟之後都可以執行特定的操作。
七. Proxy模式實現過程
以ActivityManager為例,先看一下AMS框架結構圖。
1. IActivityManager作為ActivityManagerProxy和ActivityManagerNative的公共接口,所以兩個類具有部分相同的接口,可以實現合理的代理模式;
2. ActivityManagerProxy代理類是ActivityManagerNative的內部類;
3. ActivityManagerNative是個抽象類,真正發揮作用的是它的子類ActivityManagerService(系統Service組件)。
4. ActivityManager是一個客戶端,為了隔離它與,有效降低甚至消除二者的耦合度,在這中間使用了ActivityManagerProxy代理類,所有對的訪問都轉換成對代理類的訪問,這樣ActivityManager就與解耦了,這是典型的proxy的應用場景。
5. ActivityManagerService是系統統一的Service,運行在獨立的進程中;通過系統ServiceManger獲取;ActivityManager運行在一個進程裏面,ActivityManagerService運行在另一個進程內,對象在不同的進程裏面,其地址是相互獨立的;采用Binder機制跨進程通信,所以我們可以得出這是一個RemoteProxy。
這裏涉及到兩個過程:
代理對象建立:ActivityManagerProxy代理對象的創建;
程序執行過程:如何通過代理對象來執行真正對象請求;
下面看看這兩個過程。
1. 代理對象建立
是在ActivityManager的getRunningServices執行時就需要代理類來執行;
1 public List<RunningServiceInfo> getRunningServices(int maxNum) 2 return ActivityManagerNative.getDefault().getServices(maxNum, 0); 3 }
繼續看看ActivityManagerNative.getDefault()到底幹了什麽事:實際上是關乎到Singleton<IActivityManager>類型的gDefault對象創建;
1 private static final Singleton<IActivityManager> gDefault = new 2 Singleton<IActivityManager>() { 3 protected IActivityManager create() { 4 IBinder b = ServiceManager.getService("activity"); 5 IActivityManager am = asInterface(b); 6 return am; 7 } 8 };
ServiceManager.getService("activity");獲取系統的“activity”的Service, 所有的Service都是註冊到ServiceManager進行統一管理。
這樣就創建了一個對ActivityManagerService實例的本地代理對象ActivityManagerProxy實例。Singleton是通用的單例模板類。
ActivityManagerNative.getDefault就返回一個此代理對象的公共接口IActivityManager類型,就可以在本地調用遠程對象的操作方法。
2. 程序執行過程
仍以getRunningServices方法為例,ActivityManager執行getRunningServices,創建ActivityManagerProxy實例,
其實實際執行的是ActivityManagerNative的代碼,但是ActivityManagerNative是個抽象類,所以真正有效的代碼在 ActivityManagerNative 的子類 ActivityManagerService中。
下面看一下動態時序圖:
我們以ActivityManager的getRunningServices()函數為例,對上述序列圖進行解析。
1 public List<RunningServiceInfo> getRunningServices(int maxNum) 2 throws SecurityException { 3 try { 4 return (List<RunningServiceInfo>)ActivityManagerNative.getDefault() 5 .getServices(maxNum, 0); 6 } catch (RemoteException e) { 7 // System dead, we will be dead too soon! 8 return null; 9 } 10 }
可以看到,調用被委托到了ActivatyManagerNative.getDefault()。
1 static public IActivityManager asInterface(IBinder obj){ 2 …… 3 return new ActivityManagerProxy(obj); 4 }
7 static public IActivityManager getDefault(){ 8 …… 9 IBinder b = ServiceManager.getService("activity"); 10 gDefault = asInterface(b); 11 return gDefault; 12 }
從上述簡化後的源碼可以看到,getDefault()函數返回的是一個ActivityManagerProxy對象的引用,也就是說,ActivityManager得到了一個本地代理。
因為在IActivityManager接口中已經定義了getServices()函數,所以我們來看這個本地代理對該函數的實現。
1 public List getServices(int maxNum, int flags) throws RemoteException { 2 3 Parcel data = Parcel.obtain(); 4 Parcel reply = Parcel.obtain(); 5 …… 6 mRemote.transact(GET_SERVICES_TRANSACTION, data, reply, 0); 7 …… 8 }
從這個代碼版段我們看到,調用遠端代理的transact()函數,而這個mRemote就是ActivityManagerNative的Binder接口。
接下來我們看一下ActivityManagerNative的代碼,因為該類是繼承於Binder類的,所以transact的機制此前我們已經展示了代碼,對於該類而言,重要的是對onTransact()函數的實現。
1 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 2 throws RemoteException { 3 4 switch (code) { 5 case GET_SERVICES_TRANSACTION: { 6 …… 7 List list = getServices(maxNum, fl); 8 …… 9 return true; 10 } 11 …… 12 } 13 return super.onTransact(code, data, reply, flags); 14 }
在onTrasact()函數內,雖然代碼特別多,但就是一個switch語句,根據不同的code命令進行不同的處理,比如對於 GET_SERVICES_TRANSACTION命令,只是調用了getServices()函數。而該函數的實現是在 ActivityManagerService類中,它是ActivityManagerNative的子類。
Android中的代理(Proxy)模式