1.面向?qū)ο?大原則
solidd(single, open, lishi, interface,
1 單一職責原則(優(yōu)化第一步)
一個類應該負責單一的功能,應該是一組相關性很高的函數(shù),數(shù)據(jù)的封裝,兩個完全不一樣的功能不應該放在一個類中。
2 開閉原則(程序更穩(wěn)定)
類,模塊,函數(shù)等對于拓展是開放,對于修改是關閉的,也就說重要的邏輯都是無法修改的,如果需要修改功能可以通過繼承拓展的方式來實現(xiàn)。
3 里氏替換原則(擴展性更強)
所有引用基類的地方,必須能透明的使用其子類的對象。實際上就是抽象繼承,在需要調(diào)用子類繼承方法的時候,直接用父類去調(diào),很明顯的就是android中所有的IxxxxManager,實際上拿的都是子類xxxxManagerService具體實現(xiàn)的方法
4 依賴倒置原則(項目變化能力增強)
高層不應該依賴于低層,而應該依賴低層的抽象,抽象類中不應該出現(xiàn)實現(xiàn)類。比如在工具類(高層類,相當于管理者)中,盡量不要出現(xiàn)實現(xiàn)類(低層類,最底層的class),因為這樣可能會導致,以后這個實現(xiàn)類滿足不了需求的時候需要去修改這個工具類才能達到拓展的目的。
5 接口隔離原則(更靈活)
盡量做到接口的拆分,將龐大臃腫的接口拆分成具體的接口,用戶不用每一次都去實現(xiàn)接口中它不需要的方法。
6 迪米特原則(更好的擴展性)
一個類中對其他對象了解的越少越好,全力解耦,自己做好自己的事情,其他人的事情讓他們自己去做,也不要去幫著做。
2. 單例模式
(1)餓漢模式:
public class SingleTon {
private SingleTon mInstance = new SingleTon();
public static SingleTon getInstance(){
return mInstance;
}
}
內(nèi)部持有指向自己的靜態(tài)變量
(2)懶漢模式:
public class SingleTon {
private static SingleTon mInstance;
SingleTon(){
}
public static synchronized SingleTon getInstance(){
if(mInstance == null){
mInstance = new SingleTon();
}
return mInstance;
}
}
宗旨就是持有自己的靜態(tài)私有變量,首次初始化一下,之后就一直有了。節(jié)省開銷,但是首次加載會比較慢,并且每次都需要同步,開銷略大,不建議使用。
(3)Double check lock模式
public class SingleTon {
private SingleTon mInstance;
SingleTon(){
}
public static SingleTon getInstance(){
if(mInstance == null){
sychronized(SingleTon.class){
if(mInstance == null){
mInstance = new SingleTon();
}
}
}
return mInstance;
}
}
為什么要叫double check是因為它檢查了兩次,第一次檢查完為空了之后,需要考慮到線程安全問題,上鎖再進行new,這樣就保證了只創(chuàng)建了一個SingleTon,且不用每一次調(diào)用這個方法都要進行同步。缺點也是第一次調(diào)用的時候反應比較慢,且有極小的可能會失效,但是效率較高,資源利用率也高
(4)靜態(tài)內(nèi)部類單例模式
public class SingleTon {
public static SingleTon getInstance(){
return InstanceHandler.mInstance;
}
private static class InstanceHandler{
private static final SingleTon mInstance = new SingleTon();
}
}
這種方法解決了DCL的失效問題,這是推薦使用的最好的單例模式
(5)容器實現(xiàn)單例
舉個例子,就是安卓源碼中的service注冊管理以及serviceManager注冊管理都是用的map保存。
源碼中的使用:
(1)就是上面所說的service管理
(2)ActivityMangerNative.getDefault()方法
優(yōu)缺點:
優(yōu)點:節(jié)省資源,優(yōu)化和共享資源訪問
缺點:Context內(nèi)存泄露
3. 構(gòu)造者模式
創(chuàng)建一個builder類,然后只把你用的到的參數(shù)傳進去。
源碼中的使用:
(1)AlertDialog.Builder
優(yōu)缺點:
優(yōu)點:良好的封裝性和可擴展性
缺點:產(chǎn)生了多余的Builder對象,浪費了內(nèi)存
4. 原型模式(本質(zhì)就是對象拷貝)
不通過new去生成一個對象,而直接通過clone一個已經(jīng)存在的對象來生成一個新的對象。我們只要去implements Cloneable接口,然后復寫它的clone方法即可。
(1)淺拷貝
將原始對象的所有字段統(tǒng)統(tǒng)拷貝過去,且僅僅是單純的拷貝
(2)深拷貝
對于除了基本類型的字段,采用相應數(shù)據(jù)類型的clone方法,如:
doc.mImages = (ArrayList<String>) this.mImages.clone();
源碼中的使用
(1)ArrayList的clone方法
(2)Intent的clone方法
優(yōu)缺點
優(yōu)點:直接clone,可以免去再次調(diào)用構(gòu)造函數(shù),節(jié)省資源
缺點:不會再次調(diào)用構(gòu)造函數(shù),需要注意這個潛在的問題
5. 工廠模式
一個抽象的工廠類,有一個抽象的生產(chǎn)方法。一個具體的工廠類繼承這個抽象的工廠,然后想生產(chǎn)什么就生產(chǎn)什么,只要是抽象生產(chǎn)方法返回的基類的任意子類都行。
源碼中的使用
(1)AbstractList和AbstractSet就是那個抽象工廠,這兩個抽象的工廠類里面都一個iterator的迭代器方法用來遍歷的,arrayList繼承了AbstractList有它的iterator方法實現(xiàn),HashSet和MapSet則分別是AbstractSet的具體工廠實現(xiàn)。
優(yōu)缺點
優(yōu)點:降低了對象間的耦合,將具體的實現(xiàn)交給子類去完成,增強了拓展性
缺點:如果要添加新的產(chǎn)品,就需要寫一個新的產(chǎn)品類,而且是抽象類放到工廠才行,類結(jié)構(gòu)就會變得復雜化了。
6. 抽象工廠模式
跟工廠模式不同的是,一個抽象工廠中可以有多個抽象的方法,那么具體工廠可以有多種不同的實現(xiàn)方式
源碼中的使用
(1)比如繼承了Activity的onCreate()方法,onResume()等各種生命周期的方法
(2)繼承了service,里面的onBind等方法。
優(yōu)缺點
優(yōu)點:降低了對象間的耦合,很靈活
缺點:類會變得很多,如果要添加新的產(chǎn)品,就需要寫一個新的產(chǎn)品類,而且是抽象類放到工廠才行,類結(jié)構(gòu)就會變得復雜化了。
7. 策略模式
將不同的算法都封裝起來,選擇你所需要的算法,比如我們類中常用到的需要將時間戳轉(zhuǎn)換成不同的格式,然后我們就會在一個Util類里面去定義不同的format方法。
源碼中的使用
(1)時間插值器,我們在制作動畫的時候使用到的不同的時間插值器就是不同的算法封裝
優(yōu)缺點
優(yōu)點:結(jié)構(gòu)清晰,簡單直觀;耦合較低,擴展方便;封裝徹底,數(shù)據(jù)安全。
缺點:隨著策略的越來越多,子類也會變得越來越多。
8.狀態(tài)模式
說白了就是在一個類的內(nèi)部定義一個變量,這個變量可以去控制某些方法是否可行。比如說我們在adapter中經(jīng)常使用的是否被選中啊,選中的position啊等狀態(tài)會在某些方法中需要對這些狀態(tài)進行判斷。
源碼中的使用
(1)wifi控制器,在源碼的WifiSetting中,我們就能看到我們需要去把wifi按鈕打開,才能夠繼續(xù)做wifi的連接操作,那么wifi的連接操作的方法里面就會去判斷是否已經(jīng)wifiEnable了
(2)handler的handleMessage根據(jù)which判斷也是這個道理
優(yōu)缺點
優(yōu)點:將繁瑣的狀態(tài)判斷都放在一個結(jié)構(gòu)清晰的狀態(tài)類中進行管理,增加了可擴展性和可維護性
缺點:類和對象的個數(shù)變多
9. 責任連模式
將類一環(huán)扣一環(huán),組成一個鏈,基類中定義一個next對象,并且有一個抽象method,子類實現(xiàn)的時候可以指定下一個類,并在實現(xiàn)method的時候指定如果自己沒有解決這個method可以交給下一個類來處理,這樣就是一個責任鏈模式
源碼中的使用
(1)View中的dispatchTouchEvent,如果沒有攔截就不斷的從外往里分發(fā),如果沒有消費掉觸摸事件,會不斷的從里向外專遞。
(2)handler的handleMessage根據(jù)which判斷也是這個道理
優(yōu)缺點
優(yōu)點:請求者和處理者之間的關系解耦
缺點:遍歷太多影響性能
10.解釋器模式
將特定的符號解釋其意義就是解釋器模式,比如解釋一段算數(shù)運算符,解釋一個xml文件等
源碼中的使用
(1)PackageParser解釋AndroidManifest.xml文件就是將文件中的東西都解釋出來放到自己的屬性中保存起來
(2)lambda風格底層實現(xiàn)應該也是解釋器
優(yōu)缺點
優(yōu)點:靈活的擴展性,只要文法上有所增加,我們只需要去修改相應的解釋器就行了
缺點:每條文法都需要一個解釋器,會導致類很多,很難維護,如果文法相當復雜,并不推薦使用解釋器模式
11. 命令模式
將一系列的方法都封裝起來,用戶不用去關心這個方法里面執(zhí)行了多少步驟,只需要去調(diào)用一個方法即可,哪怕這個方法中調(diào)用了很多其他的一連串的方法,對外都是隱藏的。
源碼中的使用
(1)并沒有純粹的命令模式,基本都會夾雜這其他的設計模式,比如我們?nèi)inish一個activity,看似只是單單的調(diào)用了finish方法,實際上里面有一長串相當復雜的邏輯只是都封裝起來了
優(yōu)缺點
優(yōu)點:弱耦合,控制靈活,擴展性很強
缺點:類的膨脹,大量的衍生類
12.觀察者模式
observable,當一個對象的狀態(tài)改變的時候,所有觀察它的對象都可以第一時間得到通知
源碼中的使用
(1)所有的adapter都會去設置Observer,然后當調(diào)用NotifyDataSetChanged方法的時候會通知界面更新。
(2)EventBus
(3)廣播
優(yōu)缺點
優(yōu)點:將觀察者和被觀察者完全隔離,被觀察者自己都不知道被誰觀察了,耦合度低,很靈活
缺點:觀察者多了之后會造成調(diào)試困難,如果是同步執(zhí)行的話一個觀察者卡頓會造成卡頓,這個時候需要異步的方式。
13.備忘錄模式
將狀態(tài)保存,下次再次需要使用的時候再進行恢復
源碼中的使用
(1)activity的onSaveInstanceState和onRestoreInstanceState
優(yōu)缺點
優(yōu)點:給用戶提供了可以恢復的機制,實現(xiàn)了信息封裝,用戶不用去關心保存恢復的具體細節(jié)
缺點:類的成員變多,每一次保存都會消耗掉系統(tǒng)的資源
14.迭代器模式
提供一個順序訪問內(nèi)部元素的方法,又不會暴露具體的內(nèi)部情況,使用的很多只要是實現(xiàn)了Iterator的,都是迭代器模式。
源碼中的使用
(1)數(shù)據(jù)庫的cursor就是迭代器模式
(2)ArrayList,Set等只要是數(shù)組性質(zhì)的都會有iterator方法
優(yōu)缺點
優(yōu)點:弱化了容器類和遍歷算法之間的關系,可以通過不同的iterator實現(xiàn)類去進行不同的遍歷
缺點:類文件增加
15.模板方法模式(流程封裝)
把具體的實現(xiàn)順序?qū)懰?,而將每一步具體的方法放出去讓子類實現(xiàn)的方式。
源碼中的使用
(1)Activity的生命周期
(2)AsyncTask的生命周期
優(yōu)缺點
優(yōu)點:封裝不變的部分,擴展可變的部分
缺點:可讀性降低,難以理解。
16.訪問者模式
定義一個接口,創(chuàng)建同名不同傳參的接口方法,然后實現(xiàn)這個接口的類去對不同的對象,獲取它所需要的不同的字段。這樣就達到了可以對不同的對象做不同的操作的目的了
public interface Visitor{
public void visit(Engineer engineer);
public void visit(Manager manager);
public void visit(Ceo ceo);
public void visit(Cto cto);
}
源碼中的使用
(1) 注解中的AbstractProcessor解析時,使用到的ElementVisitor接口類就是使用了訪問者模式,可以對多個不同的對象進行訪問。
優(yōu)缺點
優(yōu)點:數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)操作可以解耦,操作就做操作的事情,根據(jù)不同的傳參,來獲得不同的數(shù)據(jù)對象,職責單一。
缺點:在interface依賴了具體類二沒有依賴抽象類,違背了依賴倒置原則,在實現(xiàn)訪問者接口的子類中會去各種操作其他類的細節(jié),違反了迪米特。
17. 中介者模式mediator
專門設計一個中介者的抽象類,將事件雙方都定義在這個中介者類中,通過繼承中介者,來操作它的屬性對象。
源碼中的使用
(1) KeyguardViewMediator這個中介者類中定義了很多manager,然后在它的很多方法中對這些manager做了相應的操作。
優(yōu)缺點
優(yōu)點:避免產(chǎn)生過多的依賴,直接在中介者內(nèi)部解決。
缺點:會使邏輯變得復雜
18.代理模式
為其他對象提供一個代理用來控制對這個對象的訪問。一個proxy類對象中持有了訪問對象的引用,然后通過這個proxy的操作來達到對訪問對象數(shù)據(jù)的訪問。
源碼中的使用
(1) 所有的binder相關類中的IxxxxManager類中都會有一個proxy對象,來對遠程的binder對象進行代理訪問
優(yōu)缺點
優(yōu)點:控制對象訪問,內(nèi)部封裝,提高訪問安全
缺點:基本沒有缺點,最多就是類文件增加(設計模式的通?。?/p>
19.組合模式
將對象組合成樹形結(jié)構(gòu),比如數(shù)和節(jié)點的定義,就是組合模式。tree中定義leaf,Object中定義node等等
源碼中的使用
(1) View和ViewGroup的嵌套組合
優(yōu)缺點
優(yōu)點:適用于分層的復雜對象,讓高層的對象可以在內(nèi)部直接對整個層次結(jié)構(gòu)進行控制
缺點:新增構(gòu)件的時候會比較復雜。
20.適配器模式adapter
用戶只需要使用統(tǒng)一的接口,可以適配所有的實現(xiàn)接口。
源碼中的使用
(1) BaseAdapter
優(yōu)缺點
優(yōu)點:更好的復用性,更好的擴展性
缺點:過多使用適配會讓系統(tǒng)變得零亂復雜
21.裝飾模式Decorator
動態(tài)的給對象添加額外的職責和功能,具體類繼承基類,并在內(nèi)部持有一個基類對象,然后直接進行代理,并可以在復寫基類方法的時候去增加額外的功能。
源碼中的使用
(1) ContextWrapper繼承了Context,并且內(nèi)部持有了Context對象,但是基本都是原封不動的調(diào)用Context的方法
優(yōu)缺點
與代理模式一樣,裝飾模式更注重的是增加功能,在調(diào)用訪問對象的方法時增加一些其他的功能,而代理模式更注重的是對訪問對象本身的訪問進行控制。
22.享元模式
對于同樣的請求,保存其結(jié)果。很好的例子就是map容器,當請求的key存在的時候,就直接get出來用,如果這樣就不用反復的每一次都請求。
源碼中的使用
(1) 實際上單例我們都可以把他理解位是享元模式,比如我們在ActivityThread中的main方法定義的mLooper是共享的,就讓我們在Activity中直接定義new Handler而不需要去為handler設置looper。
優(yōu)缺點
優(yōu)點:大大的減少對象的創(chuàng)建,節(jié)省了內(nèi)存
缺點:為了使對象可以共享,需要將享元對象的部分狀態(tài)外部化,會是系統(tǒng)變得復雜。
23.外觀模式,門面模式Facade
基本第三方都是使用的這種模式,最高層接口做統(tǒng)一的接口方法封裝,然后子類去實現(xiàn)這個最高層的接口,去分別實現(xiàn)它的方法,而用戶只需要去調(diào)高層的接口方法就可以達到相應的效果,簡單易用,又隱藏了具體的實現(xiàn)。
源碼中的使用
(1) Context這個高層抽象類封裝的抽象方法,如startActivity,startService等等
優(yōu)缺點
優(yōu)點:大大的減少對象的創(chuàng)建,節(jié)省了內(nèi)存
缺點:為了使對象可以共享,需要將享元對象的部分狀態(tài)外部化,會是系統(tǒng)變得復雜。
24.橋接模式bridge
抽象部分和實現(xiàn)部分分離,抽象類中持有另外一個抽象類,通過調(diào)用方法來對另外一個抽象類進行操作,那么去繼承這個抽象類的子類,就可以對那個持有的抽象對象進行修改。
源碼中的使用
(1) 在一個類中對另外一個抽象類進行操作的都可以認為是橋接模式,比如Canvas對view進行繪制操作
(2) 比如adapter對adapterView進行操作
優(yōu)缺點
優(yōu)點:分離抽象與實現(xiàn),擴展靈活,對用戶透明
缺點:理解簡單,設計復雜。