Android 原始碼中的設計模式
面向物件的六大原則
-
單一職責原則
所謂職責是指類變化的原因。如果一個類有多於一個的動機被改變,那麼這個類就具有多於一個的職責。而單一職責原則就是指一個類或者模組應該有且只有一個改變的原因。通俗的說,即一個類只負責一項職責,將一組相關性很高的函式、資料封裝到一個類中。
-
開閉原則
對於擴充套件是開放的,這意味著模組的行為是可以擴充套件的。當應用的需求改變時,我們可以對模組進行擴充套件,使其具有滿足那些改變的新行為。
對於修改是關閉的,對模組行為進行擴充套件時,不必改動模組的原始碼。通俗的說,儘量通過擴充套件的方式實現系統的升級維護和新功能新增,而不是通過修改已有的原始碼。
-
里氏替換原則
使用“抽象(Abstraction)”和“多型(Polymorphism)”將設計中的靜態結構改為動態結構,維持設計的封閉性。任何基類可以出現的地方,子類一定可以出現。
在軟體中將一個基類物件替換成它的子類物件,程式將不會產生任何錯誤和異常,反過來則不成立。在程式中儘量使用基類型別來對物件進行定義,而在執行時再確定其子類型別,用子類物件來替換父類物件。
-
依賴倒置原則
高層次的模組不應該依賴於低層次的模組,他們都應該依賴於抽象。抽象不應該依賴於具體實現,具體實現應該依賴於抽象。
程式要依賴於抽象介面,不要依賴於具體實現。簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合(各個模組之間相互傳遞的引數宣告為抽象型別,而不是宣告為具體的實現類)。 -
介面隔離原則
一個類對另一個類的依賴應該建立在最小的介面上。其原則是將非常龐大的、臃腫的介面拆分成更小的更具體的介面。
-
迪米特原則
又叫作最少知識原則,就是說一個物件應當對其他物件有儘可能少的瞭解。
通俗地講,一個類應該對自己需要耦合或呼叫的類知道得最少,不關心被耦合或呼叫的類的內部實現,只負責呼叫你提供的方法。下面開始設計模式學習...
1. Singleton(單例模式)
作用:
保證在Java應用程式中,一個類Class只有一個例項存在。
好處:
由於單例模式在記憶體中只有一個例項,減少了記憶體開銷。
單例模式可以避免對資源的多重佔用,例如一個寫檔案時,由於只有一個例項存在記憶體中,避免對同一個資原始檔的同時寫操作。
單例模式可以再系統設定全域性的訪問點,優化和共享資源訪問。
使用情況:
建立目錄 資料庫連線的單執行緒操作
某個需要被頻繁訪問的例項物件
1.1 使用方法
第一種形式:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
但是這有一個問題,不同步啊!在對據庫物件進行的頻繁讀寫操作時,不同步問題就大了。
第二種形式:
既然不同步那就給getInstance方法加個鎖唄!我們知道使用synchronized關鍵字可以同步方法和同步程式碼塊,所以:
- 1
- 2
- 3
- 4
- 5
- 6
或是
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
獲取Singleton例項:
- 1
1.2android中的Singleton
軟鍵盤管理的 InputMethodManager
原始碼(以下的原始碼都是5.1的):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
使用的是第二種同步程式碼塊的單例模式(可能涉及到多執行緒),類似的還有
AccessibilityManager(View獲得點選、焦點、文字改變等事件的分發管理,對整個系統的除錯、問題定位等)
BluetoothOppManager等。
當然也有同步方法的單例實現,比如:CalendarDatabaseHelper
- 1
- 2
- 3
- 4
- 5
- 6
注意Application並不算是單例模式
- 1
- 2
- 3
- 4
- 5
在Application原始碼中,其構造方法是公有的,意味著可以生出多個Application例項,但為什麼Application能實現一個app只存在一個例項呢?請看下面:
在ContextWrapper原始碼中:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
ContextWrapper建構函式傳入的base為null, 就算有多個Application例項,但是沒有通過attach()繫結相關資訊,沒有上下文環境,三個字。
然並卵
2. Factory(工廠模式)
定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類。
對同一個介面的實現類進行管理和例項化建立
假設我們有這樣一個需求:
動物Animal,它有行為move()。有兩個實現類cat和dog。為了統一管理和建立我們設計一個工廠模式。
同時兩個子類有各自的行為,Cat有eatFish(),Dog有eatBone().
結構圖:
Animal介面:
- 1
- 2
- 3
Cat類:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Dog類:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
那麼現在就可以建一個工廠類(Factory.java)來對例項類進行管理和建立了.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
使用:
- 1
- 2
- 3
- 4
- 5
- 6
工廠模式在業界運用十分廣泛,如果都用new來生成物件,隨著專案的擴充套件,animal還可以生出許多其他兒子來,當然兒子還有兒子,同時也避免不了對以前程式碼的修改(比如加入後來生出兒子的例項),怎麼管理,想著就是一團糟。
- 1
這裡例項化了Animal但不涉及到Animal的具體子類(減少了它們之間的偶合聯絡性),達到封裝效果,也就減少錯誤修改的機會。
Java面向物件的原則,封裝(Encapsulation)和分派(Delegation)告訴我們:具體事情做得越多,越容易範錯誤,
一般來說,這樣的普通工廠就可以滿足基本需求。但是我們如果要新增一個Animal的實現類panda,那麼必然要在工廠類裡新增了一個生產panda的方法。就違背了 閉包的設計原則(對擴充套件要開放對修改要關閉) ,於是有了抽象工廠模式。
2.1 Abstract Factory(抽象工廠)
抽象工廠模式提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。
啥意思?就是把生產抽象成一個介面,每個例項類都對應一個工廠類(普通工廠只有一個工廠類),同時所有工廠類都繼承這個生產介面。
生產介面Provider:
- 1
- 2
- 3
每個產品都有自己的工廠
CatFactory: