標籤:
抽象工廠應用是很廣的,在Android源碼中,這個IPolicy就是一個簡單的抽象原廠模式。下面分析一下IPolicy及其實現,以及建立的相關對象(源碼基於5.0.0)。
抽象工廠意圖
提供一個建立一系列相關或相互依賴對象的介面,而無需指定他們具體的類。
UML類圖
通過繼承抽象工廠,可以產生不同的產品系列
程式碼範例
abstract class AbsFactory{ public abstract AbsProductA createProduct1(); public abstract AbsProdcutB createProduct2(); } abstract class AbsProductA{ } abstract class AbsProductB{ } class ProductA1 extends AbsProductA{ } class ProductB1 extends AbsProductB{ public void interactWithProductA(AbsProductA product){ //與ProductA關聯 } } class ConcreteFactory1 extends AbsFactory{ private static ConcreteFactory instance = new ConcreteFactory(); public ConcreteFactory getInstance(){ return instance; } public AbsProductA createProductA(){ return new ProductA1(); } public AbsProdcutB createProductB(){ return new ProductB1(); } } public static void main(String[] args){ ConcreteFactory instance = ConcreteFactory. AbsProductA product1 = instance.createProductA(); AbsProductB product2 = instance.createProductB(); product2.interactWithProductA(product1); }
抽象工廠就是建立一系列相互關聯的對象,這樣每一個抽象工廠的具體實現建立的對象都是相互關聯的,而且可以是不同的產品系列,相當於從上層就設計好了一套產品規範。這裡只是簡單介紹了一下抽象工廠。如果想很好的理解可以參考設計模式:可複用物件導向軟體的基礎關於抽象工廠的介紹。下面介紹IPolicy。
IPolicy
IPolicy在com.android.internal.policy包下面。它是關於Android視窗,視窗管理,布局載入,以及事件回退Handler這一系列視窗相關產品的抽象工廠。先看IPolicy的UML類圖。
UML圖
IPolicy是產生視窗螢幕相關對象的抽象介面,在Android手機源碼中,com.android.internal.policy.impl.Policy是它的唯一一個實現,按照源碼中的注釋所說的,是Policy是IPolicy的一個簡單實現,用來產生對象集合。Policy建立一系列的Phone的視窗相關對象:PhoneWindow,PhoneLayoutInflater,PhoneWindowManager,PhoneFallbackEventHandler。從UML圖就可以看出,IPolicy算是一個典型的抽象工廠,只不過在源碼中只有一個具體的工廠實現。
另外Policy的實現還有一點特殊的地方,它使用static域將他需要建立的對象都預先load出來,也就是說當虛擬機器載入Policy類的時候,就會載入它建立的對象的class。
相關對象介紹
下面分別介紹IPolicy建立的每個對象
PolicyManager
PolicyManager相當於是這個抽象工廠的用戶端,它只有靜態方法,他它的靜態方法跟IPolicy的介面是相對應的。它內部包含了一個Policy對象,相當於是Policy的一個代理,對應的建立操作都會交給Policy去建立,比如說makeNewWindow方法的實現:
// The static methods to spawn new policy-specific objectspublic static Window makeNewWindow(Context context) { return sPolicy.makeNewWindow(context);}
Window與PhoneWindow
Window是Android中的視窗,每個Activity都會對應著一個Window,在Activity的attach方法中,就有Window的建立代碼:
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, IVoiceInteractor voiceInteractor) { attachBaseContext(context); mFragments.attachActivity(this, mContainer, null); mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); ...
attach方法是將Context,application等賦值給Activity,在Activiy啟動的過程會調用。我們彈出的對話方塊(Dialog),裡面也是有一個Window的。另外與Activity對應的還有啟動視窗(Starting Window)。一個Window還可以有子Window。另外Android中還有一些其他的視窗還有IME視窗,狀態列視窗,壁紙視窗。
視窗有一個專門的視窗管理服務WindowManagerService,在WindowManagerService中與每個Activity對應的為AppWindowToken,而AppWindowToken描述的是一組視窗(一組WindowState),對應於Activity中Context的各種視窗。
而手機中, Window的具體實現是PhoneWindow。PhoneWindow是對應著Android手機的Window實現。PhoneWindow裡麵包含了DecorView, DecorView包含了標題列以及具體View(由setContentView設定)。它們之間的關係如下:
而真正直接關聯Window與View的是WindowManager,由Window.setWindowManager設定。每個Window都會對應一個WindowManager。通過WindowManager的addView,updateViewLayout,removeView來添加,更新,移除Window中的View。
通過context.getSystemService(Context.WINDOW_SERVICE)可以獲得WindowManager,這個就是Activity的mWindow的WindowManager,而WindowManager的具體實現是WindowManagerImpl,而WindowManagerImpl又會將Window的相關操作(addView, removeView)交給WindowManagerGlobal來實現。WindowManagerGlobal是一個單例模式,裡麵包含了一個ViewRootImpl列表(ArrayList),一個View列表, 一個WindowManager.LayoutParams列表,三個鏈表相互對應,表示一個View對應的LayoutParams和ViewRoot。WindowManagerGlobal擷取了WindowManagerService的Binder介面IWindowManager。ViewRootImpl通過WindowManagerGlobal的IWindowManager擷取WindowSession(Binder的Proxy),將ViewRootImpl的W(Binder對象)傳給WindowManagerService,來與WindowManagerService相互連信。他們之間的UML圖如下:
WindowManagerPolicy,PhoneWindowManager
這個WindowManagerPolicy不同於Window中介紹的WindownManager,Window中介紹的WindowManager是屬於Window與View互動的管理,而WindowManagerPolicy則是更多地傾向於對Window螢幕的管理,比如說啟動視窗就是由它建立的。也包括一個具體的螢幕管理,比如說擷取螢幕顯示的大小,旋轉螢幕,螢幕設定等等。PhoneWindowManager是WindowManagerPolicy在手機規格下的實現。WindowManagerPolicy還有一個內部靜態類WindowManagerPolicy.WindowState,它是由WindowManagerService管理的,從一個視窗開始添加就存在,到視窗移除就刪除,是一個視窗的狀態介面,可以獲得當前視窗所屬的進程,包名,當前的Frame
LayoutInflater,PhoneLayoutInflater
LayoutInflater應該都比較熟悉,它是Android中用於XML布局載入的類,它是一個抽象類別,PhoneLayoutInflater是它在Android手機上面的實現。PhoneLayoutInflater中主要是實現了onCreateView方法和cloneInContext方法。
FallbackEventHandler,PhoneFallbackEventHandler
這個是回退事件Handler,主要是為了處理回退事件(Fallback)。
IPolicy抽象工廠的設計分析
如果只看IPolicy,PolicyManager,Policy的UML,你會發現其實這三個部分也像是一個策略模式的UML圖。這部分裡面本身也可以說是一種策略,一種建立的策略。但把IPolicy作為抽象工廠理解會更為合適,它負責產生一系列相關產品,卻不用管產品的具體實現。
首先說說這四個產品之間的關係,Window是表示視窗,抽象的視窗管理,而WindowManagerPolicy是關於視窗螢幕的管理原則,LayoutInflater是XML解析器,將XML解析為Window中具體元素View,最後FallbackEventHandler是回退事件Handler,事件會作用在視窗上面。這四個產品在不同的產品簇的具體表現會是不一樣的,但是他們又有相互之間的關聯。用一個統一的建立介面,在使用這些介面的時候會更加方便。
就拿Phone的這四種產品實現來說,Phone的Window,以及WindowManagerPolicy自然是不同的,另外LayoutInflater也會有所不同,比如XML的View可能限制不一樣,在PhoneLayoutInflater中會從包名首碼為”android.widget.”,”android.webkit.”,”android.app.”這三個來建立View。另外如果產品簇是TV的話,FallbackEventHandler處理可能是直接回退到上一個台,而Phone的話會是返回上一個操作。
用四個Factory 方法實現
其實四種不同的產品(Window,WindowManagerPolicy,LayoutInflater,是XML解析器,將XML解析為Window中具體元素View,最後FallbackEventHandler),如果用四個Factory 方法也肯定是可以的,但是會缺乏將本來應該有相互關聯的產品拆分開了,抽象工廠一定程度上提高了它們之間的耦合性。
擴充優勢分析
假如除了Phone外,又突然有了一種新的產品簇(比如說TV,智能手錶,我暫時並沒有調查這兩種的實現方式),那麼只需要建立一個對應Policy,以及對應的產品系列,然後將PolicyManager的IPolicy指向新產品簇的Policy就好了。
Android源碼中的抽象工廠---IPolicy