編輯:關於Android編程
適配器模式通過對另外的類或對象的包裝,將其接口轉換為用戶期望的接口,達到接口適配的目的。
外觀模式是對包裝的一組類或對象提供一個高層接口,意圖是簡化接口,使系統更加容易使用。
裝飾模式的意圖是在不改變包裝對象接口的情況下為其增加另外的功能或職責。
代理模式的意圖是通過對包裝對象的包裝以便控制對包裝對象的訪問。
適配器模式、外觀模式對客戶提供的接口與其包裝類的接口有所不同,也就是這兩種模式對客戶來說改變了包裝類的訪問接口。而裝飾模式、代理模式對外不改變所包裝類的接口,對客戶提供的接口與包裝類的接口相同。
1適配器模式
適配器模式包括兩種:類適配器模式和對象適配器模式,一種使用了繼承方式,一種使用了對象組合方式,相關的UML類圖如下:
Android系統中適配器模式大量采用,由於ANDROID采用的是JAVA語言,而JAVA語言不支持多繼承,因此在系統中采用的適配器模式主要是第二種,用來把包裝對象的接口轉換為需要的接口。
在Android系統中最常用的采用適配器模式的類為繼承於BaseAdapter的類,如ArrayAdapter、CursorAdapter等,用來在底層數據和AdapterView視圖之間提供適配,把對底層數據的讀取接口轉換為視圖需要的接口。類圖如下:
繼承於AdapterView的視圖(Client)通過Adapter(Target)的接口函數獲得視圖需要的數據,如Adapter接口函數getItem(int position)從底層數據集獲得位置position的數據項,getCount()函數獲得數據集中的數據項的個數。
Adapter的具體類完成與不同底層數據類型讀取接口的適配,如CursorAdapter類通過Cursor對象讀取底層數據庫中的數據,ArrayAdapter用來讀取任意類型列表數組中的數據,HistoryAdapter用來讀取類型為HistoryEntry的向量中的數據。
其它采用適配器模式的還有顯示服務中DisplayAdapter類以及打印服務中的PrintDocumentAdapter類。DisplayAdapter用來適配不同類型的顯示設備,用來偵測和發現系統連接的不同類型的設備。PrintDocumentAdapter用來適配不同的打印輸出目標設備,如打印機或者文件,用來在這些設備輸出打印內容。
2 、外觀模式
外觀模式的類圖如下:
在Android 系統中使用的外觀模式的地方比較多,可以說每個系統服務都對客戶提供了一個訪問該系統服務的管理門戶類,用來方便訪問對應的系統服務,如窗口管理服務對應的WindowManager,輸入管理服務對應的InputManager,活動管理服務對應的ActivityManager等等。
另外ContentResolver、Log、Context、ServiceManager也可以看作門戶模式的采用。
ContentResolver用來為應用提供訪問數據模式的公共接口,Log為應用提供使用log輸出系統的公共接口,Context為應用提供訪問整個系統的接口。ServiceManager提供訪問其它系統服務的入口。
在Android系統中也有不少使用裝飾模式的例子。如ContextThemeWrapper類及其派生類Activity和Service。UML類圖如下:
ContextWrapper是對ContextImpl類的包裝,Service類和Activity類都是ContextWrapper的派生類,Service類直接派生自ContextWrapper,Activity間接派生自ContextWrapper的子類ContextThemeWrapper,Service類和Activity類分別在ContextWrapper和ContextThemeWrapper類的接口基礎上添加和實現了各自的生命周期回調接口(鉤子),Activity類還提供了與其相關的窗口和視圖顯示相關的功能。ContextThemeWrappe的功能是在ContextWrapper基礎上添加了對主題(Theme)的支持及在通過getSystemService接口返回服務管理對象時對於LAYOUT_INFLATER_SERVICE服務做了特殊處理,采用原形模式返回一個LayoutInflater對象的克隆對象。
4 、代理模式
代理模式的類圖如下:
在Android系統中代理模式也是普遍采用,每一個系統服務和本地服務都對應一個遠端代理類,用來實現跨進程的訪問系統服務或本地服務。每一個系統服務為一個Stub對象,而客戶端通過一個Proxy對象訪問對應的Stub對象。如管理管理服務對應的類圖如下:
WindowManagerGlobal作為客戶通過繼承於接口IWindowManager的一個代理對象IWindowManager.Stub.Proxy跨進程訪問系統服務WindowManagerService。
5 、橋接模式
橋接模式的意圖為:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。這裡的抽象和實現指的不是類的抽象和實現,而可以理解為功能抽象(或界面)和功能實現。任何具有實現關系的兩個獨立演化派生的類之間都可以構成橋接模式,橋接模式主要用在需要跨越多個平台的圖形和窗口系統上。如所有介紹橋接模式的書中幾乎都是以不同特性的窗口與窗口功能的實現,不同的視圖(或圖形)與視圖(或圖形)的繪制作為采用橋接模式的例子。如下為橋接模式的類圖結構:
同樣在ANDROID系統中不同的視圖構成的視圖樹與完成視圖的繪制功能的類之間,以及窗口類與窗口的功能實現類之間也可以認為采用的是橋接模式。相關類圖如下:
圖中不同的視圖如Button、ImageView、TextView構成了一個抽象派生層次視圖樹,在視圖樹中View是所有視圖的根視圖,View的繪制通過三個不同的能獨立演化的類來實現:Canvas(提供繪制表面)、HardwareLayer(提供輸出顯示層)、DisplayList(代表一個繪制操作)。
如下為ANDROID系統中窗口與窗口實現類之間的類圖。Window、PhoneWindow構成窗口的抽象部分,Window是抽象部分的抽象接口,Window目前只提供了一個具體類PhoneWindow,Window的實現部分相關的類也構成了一個派生類圖,WindowManager為窗口實現部分的基類,WindowManagerImpl為WindowManager的具體類,WindowManagerImpl通過WindowManagerGlobal並通過IWindowManager接口與窗口管理服務WindowManagerService交互,由窗口管理服務完成實際的窗口管理功能。
橋接與適配器兩個模式非常類似,只是使用場合和觀察角度不同。
在GOF所著的設計模式經典著作中對橋接模式與適配器模式的區別描述為:B r i d g e模式的結構與對象適配器類似,兩個模式的不同之處主要在於它們各自的用途和出發點:B r i d g e目的是將接口部分和實現部分分離和橋接,從而對它們可以較為容易也相對獨立的加以改變和演化,B r i d g e模式能夠為用戶提供一個穩定的抽象和其實現接口。而A d a p t e r模式通過改變一個已有對象的接口,用來解決兩個已有接口之間的不匹配,幫助實現不兼容的類之間協同工作,A d a p t e r模式不考慮這些接口是怎樣實現的,也不對其重新設計,也不考慮它們各自可能會如何演化。因此A d a p t e r通常在系統設計完成後使用,而B r i d g e模式必須事先知道一個抽象將有多個實現部分,因此在系統開始時就被使用。
因此從上面的描述可以看出:對一個采用橋接或適配器模式的已經完成的代碼,從不同的觀察角度可以看作橋接模式,也可以看作適配器模式。
6 、組合模式
組合模式的意圖為:將對象組合成樹形結構以表示“部分-整體”的層次結構。C o m p o s i t e使得用戶對單個對象和組合對象的使用具有一致性。如下為類圖結構:
采用組合模式的標准例子為圖形、視圖、菜單和窗口等,集合類(如數組)、文件目錄也可以看作采用了組合模式。如下為ANDROID系統中采用組合模式的組合視圖類圖:
享元模式的意圖為運用共享技術有效地支持大量細粒度的對象,類圖結構如下:
享元模式也是普遍采用的模式。
在ANDROID系統中,每個應用組件都可以使用系統提供的眾多服務管理對象,如WallpaperManager、AccessibilityManager、CaptioningManager、AccountManager等等。因此為了在一個組件內共享這些對象,在應用組件的Context的實現ContextImpl中,在ContextImpl類第一次加載引用時為每個管理對象都創建了一個ServiceFetcher對象(采用靜態代碼塊),並根據服務名字把新創建的ServiceFetcher對象放到MAP集合中,每個ServiceFetcher對象在登記到MAP集合中時都分配了一個索引。
應用組件在調用Context.getSystemService來獲得系統服務管理對象時,首先根據服務名字從MAP集合中獲得對應的ServiceFetcher對象,然後調用ServiceFetcher對象的getService函數獲得ServiceFetcher對象創建的服務管理對象。
在ServiceFetcher對象的getService函數中首先從Context維護的Cache數組列表中根據ServiceFetcher對象的索引查找是否已經包含有ServiceFetcher對象創建的服務管理對象,如果在Cache中存在服務管理對象,則直接返回Cache中保存的服務管理對象,否則調用ServiceFetcher的createService函數創建一個服務管理對象,並根據其索引放置到Cache中,以便下次使用。
版權所有,請轉載時清楚注明出處和鏈接,謝謝!
在上一篇《Android仿微信滑動彈出編輯、刪除菜單效果、增加下拉刷新功能》裡,已經帶著大家學習如何使用SwipeMenuListView這一開源庫實現滑動列表彈出菜單,
在使用WebView加載網頁時有時候網速等原因加載比較慢時,為了避免在加載網頁的時候出現一片空白的區域,給用戶很不好的體驗感,我們往往在加載的時候添加一個進度條,使用戶直
在Android中,UI主線程並非線程安全的,所有UI相關的操作均需在UI主線程中完成。在默認情況下,開發者創建的Service、Activity、Broadcast均運
在android系統中主要提供了三種方式用於簡單的實現數據持久化功能,即文件存儲,SharePreference存儲以及數據庫存儲。當然還可以把數據保存到SD卡中。