面試複習——Android工程師之設計模式
設計模式六大原則
1、開閉原則
對擴充套件開放,對修改關閉。在程式需要進行拓展的時候,不能去修改原有的程式碼
2、里氏代換原則
所有引用父類的地方必須能透明地使用其子類的物件
3、依賴倒轉原則
這個原則是開閉原則的基礎,具體指標對介面程式設計,依賴於抽象而不依賴於具體
4、介面隔離原則
使用多個隔離的介面,比使用單個介面要好。降低類之間的耦合度
5、迪米特法則(最少知道原則)
一個實體應當儘量少地與其他實體之間發生相互作用,使得系統功能模組相對獨立
6、合成複用原則
儘量使用合成/聚合的方式,而不是使用繼承
單例模式
1、概念
單例模式是一種物件建立模式,它用於產生一個物件的具體例項,它可以確保系統中的一個類只產生一個例項
2、好處
- 省略建立物件所花費的時間
- 對系統記憶體的使用頻率降低,減輕GC壓力,縮短GC停頓時間
3、六種寫法
- 餓漢模式
public class HungurySingleton {
private static final HungurySingleton mHungurySingleton = new HungurySingleton();
private HungurySingleton(){
}
public static HungurySingleton getHungurySingleton() {
return mHungurySingleton;
}
}
不足:無法對instance例項做延時載入
優化:懶漢模式
- 懶漢模式
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
不足:在多執行緒併發時無法保證例項唯一
優化:懶漢執行緒安全
- 懶漢執行緒安全
public class LazySafetySingleton {
private static LazySafetySingleton instance;
private LazySafetySingleton (){
}
//方式一
public static synchronized LazySafetySingleton getInstance() {
if (instance == null) {
instance = new LazySafetySingleton();
}
return instance;
}
//方式二
public static LazySafetySingleton getInstance1() {
synchronized (LazySafetySingleton.class) {
if(instance == null){
instance = new LazySafetySingleton();
}
}
return instance;
}
}
不足:效能較低
優化:DCL
- DCL(雙檢查鎖機制)
public class DclSingleton {
private static volatile DclSingleton mInstance = null;
private DclSingleton() {
}
public static DclSingleton getInstance() {
if (mInstance == null) {
synchronized (DclSingleton.class) {
if (mInstance == null) {
mInstance = new DclSingleton();
}
}
}
return mInstance;
}
}
不足:JVM的即時編譯器中存在指令重排序的優化
解決:將例項設定為Volatile
優化:靜態內部類/列舉
- 靜態內部類
public class StaticInnerSingleton {
private StaticInnerSingleton() {
}
public static StaticInnerSingleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final StaticInnerSingleton sInstance = new StaticInnerSingleton();
}
}
優點:
- 運用類中靜態變數的唯一性
- JVM本身同步控制機制(final、static)保證了執行緒安全
- 沒有使用Synchronized,保證了效能的優化
靜態內部類是私有的,除了外部類其他是無法訪問的
列舉
public enum EnumSingleton {
INSTANCE;
public void doSomeThing() {
}
}
優點:
- 寫法簡單/執行緒安全(限於只有列舉的例項方法)
4、Android中的單例
application、eventBus
建造者模式
1、概念
建造者模式是較為複雜的建立型模式,它將客戶端與包含多個組成部分的複雜物件的建立過程分離
2、使用場景
當構造一個物件需要很多引數的時候,並且引數的個數或者型別不固定的時候
3、UML圖分析
4、在Android中應用
AlertDialog、Glide、OkHttp
介面卡模式
1、概念
將一個介面轉換成客戶希望的另一個介面,介面卡模式使介面不相容的那些類可以一起工作,其別名又稱包裝類
2、分類
- 類介面卡
- 物件介面卡
3、類介面卡定義
類的介面卡模式把適配的類的API轉換成為目標類的API
4、類介面卡UML圖分析
5、物件介面卡定義
與類的介面卡模式一樣,物件的介面卡模式把被適配的類的API轉換成為目標類的API,與類的介面卡模式不同的是,物件的介面卡模式不是使用繼承關係連線到Adaptee類,而是使用委派關係連線到Adaptee類
6、物件介面卡UML圖分析
7、在Android中應用
BaseAdapter類
裝飾模式
1、概念
動態地給一個物件增加一些額外的職責,就增加物件功能來說,裝飾模式比生成子類實現更為靈活
2、使用場景
- 在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責
- 當不能採用整合的方式對系統進行拓展或者採用繼承不利於系統拓展和維護時可以使用裝飾模式
3、UML圖分析
4、優點
- 對於拓展一個物件的功能,裝飾模式比繼承更加靈活,不會導致類的個數急劇增加
- 可以通過一種動態的方式來拓展一個物件的功能
- 可以對一個物件進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合
5、在Android中應用
context類
外觀模式
1、概念
外觀模式的主要目的在於讓外部減少與子系統內部多個模組的互動,從而讓外部能夠更簡單得使用子系統,它負責把客戶端的請求轉發給子系統內部的各個的模組進行處理
2、使用場景
- 當你要為一個複雜子系統提供一個簡單介面時
- 客戶程式與抽象類的實現部分之間存在很大的依賴性
- 當你需要構建一個層次結構的子系統時
3、UML圖分析
4、優點
- 由於Facade類封裝了各個模組互動的過程,如果今後內部模組呼叫關係發生了變化,只需要修改Facade實現就可以了
- Facade實現是可以被多個客戶端呼叫的
5、在Android中應用
contextImpl類
組合模式
1、概念
將物件以樹形結構組織起來,以達到“部分-整體”的層次結構,使得客戶端對單個物件和組合物件的使用具有一致性
2、使用場景
- 需要表示一個物件整體或部分層次
- 讓客戶能夠忽略不同物件層次的變化
3、UML圖分析
UML圖的Composite理解成Container容器更為合適,Container容器會包含有多個Component元件
4、優點
- 高層模組呼叫簡單
- 節點自由增加
5、在Android中應用
View、ViewGroup
策略模式
1、概念
定義一系列的演算法,把它們一個個封裝起來,並且使他們可互相替換,本模式使得演算法可獨立於使用它的客戶而變化
2、使用場景
一個類定義了多種行為,並且這些行為在這個類的方法中以多個條件語句的形式出現,那麼可以使用策略模式避免在類中使用大量的條件語句
3、UML圖分析
4、優點
- 上下文(Context)和具體策略(AbstractStrange)是鬆耦合關係
- 策略模式滿足“開閉原則”
5、在Android中應用
Volley、屬性動畫、插值器
模板方法模式
1、概念
模板方法是通過定義一個演算法骨架,而將演算法中的步驟延遲到子類,這樣子類就可以複寫這些步驟的實現來實現特定的演算法
2、使用場景
- 多個子類有公有的方法,並且邏輯基本相同時
- 重要、複雜的演算法,可以把核心演算法設計為模板方法
- 重構時,模板方法模式是一個經常使用的模式
3、UML圖分析
4、在Android中應用
Activity和Fragment生命週期、AsyncTask、BaseActivity
觀察者模式
1、概念
定義物件之間的一種一對多依賴關係,使得每當一個物件狀態發生改變時,其相關依賴物件皆得到通知並被自動更新
2、使用場景
- 一個抽象模型由兩個方面,其中一個方面依賴於另一個方面
- 一個物件的改變將導致一個或多個其他物件也發生改變
- 需要在系統中建立一個觸發鏈
3、UML圖分析
4、在Android中應用
ListView、RxJava
責任鏈模式
1、概念
是一個請求有多個物件來處理,這些物件是一條鏈,但具體由哪個物件來處理,根據條件判斷來確定,如果不能處理會傳遞給該鏈中的下一個物件,直到有物件處理它為止
2、使用場景
- 有多個物件可以處理同一個請求,具體哪個物件處理該請求待執行時刻再確定
- 在不明確指定接收者的情況下,向多個物件中的一個提交一個請求
- 可動態指定一組物件處理請求,客戶端可以動態建立職責鏈來處理請求
3、UML圖分析
4、在Android中應用
try-catch語句、有序廣播、事件分發機制
代理模式
1、概念
給目標物件提供一個代理物件,並由代理物件控制目標物件的引用
2、使用場景
- 需要為一個物件再不同的地址空間提供區域性的代表時
- 需要建立開銷非常大的物件時
- 需要控制對原始物件的訪問時
- 需要在訪問物件時附加額外操作時
3、UML圖分析
4、在Android中應用
ActivityManagerProxy、ActivityManagerNatvie