前言
最近復習設計模式茁帽,花了不少時間玉罐,由于項目經(jīng)驗還比較少,雖然看得懂潘拨,能理解吊输,但鑒于個人比較偏實踐,不善于記憶铁追,隔一段時間后季蚂,卻很快就忘記了o(╯□╰)o,到真正自己說的時候也說不出來……與其看別人的總結琅束,不如自己再根據(jù)別人的博客再思考整理一番扭屁,或許這樣比反復看的效果會好些吧。下面是根據(jù)別人的博客和以下幾點思考方式來重新整理的筆記:
1.這種模式怎么理解涩禀?(盡量簡單易懂)
2.類圖怎樣畫疯搅?(代碼怎樣寫)
3.舉個栗子?(使用場景)
4.使用這種模式有什么優(yōu)缺點埋泵?(遵循什么原則)
相關代碼示例地址: navyifanr/AndroidTrainingDemo/DesignPattern
設計模式六大原則
1.開閉原則(Open Close Principle)
開閉原則就是說對擴展開放幔欧,對修改關閉。在程序需要進行拓展的時候丽声,不能去修改原有的代碼礁蔗,實現(xiàn)一個熱插拔的效果。所以一句話概括就是:為了使程序的擴展性好雁社,易于維護和升級浴井。想要達到這樣的效果,我們需要使用接口和抽象類霉撵,后面的具體設計中我們會提到這點磺浙。
參考:https://realm.io/cn/news/donn-felker-solid-part-2/
2.里氏代換原則(Liskov Substitution Principle)
里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一洪囤。 里氏代換原則中說,任何基類可以出現(xiàn)的地方撕氧,子類一定可以出現(xiàn)瘤缩。 LSP是繼承復用的基石,只有當衍生類可以替換掉基類伦泥,軟件單位的功能不受到影響時剥啤,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為不脯。里氏代換原則是對“開-閉”原則的補充府怯。實現(xiàn)“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現(xiàn)防楷,所以里氏代換原則是對實現(xiàn)抽象化的具體步驟的規(guī)范牺丙。—— From Baidu 百科
參考:https://realm.io/cn/news/donn-felker-solid-part-3/
3.依賴倒轉原則(Dependence Inversion Principle)
這個是開閉原則的基礎复局,具體內(nèi)容:真對接口編程冲簿,依賴于抽象而不依賴于具體。
參考:https://realm.io/cn/news/donn-felker-solid-part-5/
4.接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口肖揣,比使用單個接口要好民假。還是一個降低類之間的耦合度的意思浮入,從這兒我們看出龙优,其實設計模式就是一個軟件的設計思想,從大型軟件架構出發(fā)事秀,為了升級和維護方便彤断。所以上文中多次出現(xiàn):降低依賴,降低耦合易迹。
參考:https://realm.io/cn/news/donn-felker-solid-part-4/
5.迪米特法則(最少知道原則)(Demeter Principle)
為什么叫最少知道原則宰衙,就是說:一個實體應當盡量少的與其他實體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對獨立睹欲。
6.合成復用原則(Composite Reuse Principle)
原則是盡量使用合成/聚合的方式供炼,而不是使用繼承。
模式分類
創(chuàng)建型:單例模式窘疮、簡單工廠模式袋哼、工廠方法模式、抽象工廠模式闸衫、建造者模式涛贯、原型模式;
結構型:代理模式蔚出、適配器模式弟翘、裝飾器模式虫腋、橋接模式、組合模式稀余、享元模式悦冀、外觀模式;
行為型:觀察者模式滚躯、模板方法模式雏门、命令模式、狀態(tài)模式掸掏、職責鏈模式茁影、解釋器模式 、中介者模式丧凤、訪問者模式募闲、策略模式搓逾、備忘錄模式澈歉、迭代器模式奢米;
創(chuàng)建者模式
1.單例模式(Singleton)
(1)理解:
保證一個類僅有一個實例林说,并提供一個獲得該實例的方法(必須是靜態(tài)方法吮成,通常用getInstance命名)
(2)類圖:
常使用的實現(xiàn)方法是這兩種稽物,懶漢單例模式和DCL單例模式可參考巢价,單例設計模式的N中Java實現(xiàn)方法
(3)栗子:
android中有很多系統(tǒng)級別的全局變量倒得,如時間农渊,輸入法患蹂,如InputMethodManager,賬戶砸紊,狀態(tài)欄等传于,android中對這些都直接或者有些間接用到了單例模式。
(4)優(yōu)缺點:
餓漢式:
優(yōu):線程安全醉顽,調(diào)用時反應速度快沼溜,在類加載的同時已經(jīng)創(chuàng)建好了一個靜態(tài)對象(創(chuàng)建的唯一對象);
缺:資源利用效率不高游添,可能該實例并不需要系草,但也被系統(tǒng)加載了,在一些場景下是無法使用的唆涝,比如找都,如果Single實例的創(chuàng)建依賴參數(shù)或配置文件,則在getInstance()之前必須調(diào)用某個方法來設置這些參數(shù)石抡,但在設置之前檐嚣,可能已經(jīng)new了Single實例;static 內(nèi)部類式:
優(yōu):線程安全,資源利用率高,不執(zhí)行getInstance就不會被實例嚎京。
缺:第一次加載時反應不快嗡贺。
總之,單例模式鞍帝,省去了new操作符诫睬,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC壓力帕涌;有些類如交易所的核心交易引擎摄凡,控制著交易流程,如果該類可以創(chuàng)建多個的話蚓曼,系統(tǒng)容易亂亲澡,使用單例模式,才能保證核心交易服務器獨立控制整個流程纫版。
2.簡單工廠模式
(1)理解
建立一個工廠類床绪,對實現(xiàn)了同一接口的一些類進行實例的創(chuàng)建。
(2)類圖
(3)栗子
出現(xiàn)了大量的產(chǎn)品需要創(chuàng)建其弊,并且具有共同的接口時使用癞己,但一般采用工廠方法模式。
(4)優(yōu)缺點
優(yōu):簡單粗暴
缺:如果傳入的字符串有誤梭伐,不能正確創(chuàng)建對象痹雅,而且代碼比較臃腫,擴展性不強糊识。
3.工廠方法模式(Factory Method)
(1)理解
用于創(chuàng)建對象的接口绩社,讓子類決定實例化哪個類。工廠方式模式使一個類的實例化延遲到其子類技掏。
(2)類圖
(3)栗子
如铃将,Java的ThreadFactory项鬼。希望工廠與產(chǎn)品的種類對客戶端保持透明哑梳,給客戶端提供一致的操作,另外一種是不同的工廠和產(chǎn)品可以提供客戶端不同的服務或功能绘盟。
(4)優(yōu)缺點
優(yōu):可派生多個產(chǎn)品鸠真,容易擴展性,遵循單一職責龄毡、依賴倒置
缺:類的創(chuàng)建依賴工廠類吠卷,也就是說,如果想要拓展程序沦零,必須對工廠類進行修改祭隔,這違背了閉包原則,所以可以考慮使用抽象工廠模式路操。
4.抽象工廠模式(Abstract Factory)
(1)理解
創(chuàng)建多個工廠類疾渴,一旦需要增加新的功能千贯,直接增加新的工廠類就可以了,不需要修改之前的代碼搞坝。
(2)類圖
(3)栗子
如Java的List接口搔谴,軟件的換皮膚功能;需要一個接口可以提供一個產(chǎn)品族桩撮,且不必知道產(chǎn)品的具體種類
(4)優(yōu)缺點
優(yōu):遵循單一職責敦第、依賴倒置、開閉原則店量,當需要擴展一個功能時芜果,只需做一個實現(xiàn)類,實現(xiàn)Sender接口融师,同時做一個工廠類师幕,實現(xiàn)Provider接口,就OK了诬滩,無需去改動現(xiàn)成的代碼霹粥。
注:
三種工廠模式的區(qū)別:
簡單工廠:用來生產(chǎn)同一等級結構中的任意產(chǎn)品,對于增加新的產(chǎn)品疼鸟,無能為力后控。
工廠方法:用來生產(chǎn)同一等級結構中的固定產(chǎn)品,支持增加任意產(chǎn)品空镜。
抽象工廠:用來生產(chǎn)不同產(chǎn)品族(由不同產(chǎn)品組合成的一套產(chǎn)品)的全部產(chǎn)品浩淘,對于增加新的產(chǎn)品,無能為力吴攒;支持增加產(chǎn)品族张抄。
參考:抽象工廠模式詳解
5.建造者模式(Builder)
(1)理解
將一個復雜對象的構建和它的表示分離,使得同樣的創(chuàng)建過程可以創(chuàng)建不同的表示洼怔。
工廠類模式提供的是創(chuàng)建單個類的模式署惯,而建造者模式則是將各種產(chǎn)品集中起來進行管理,用來創(chuàng)建復合對象镣隶,所謂復合對象就是指某個類具有不同的屬性极谊,其實建造者模式就是前面抽象工廠模式和最后的Test結合起來得到的。
(2)類圖
或許安岂,《Effective Java》的例子更好轻猖,遇到多個構造參數(shù)時要考慮用構建器(Builder模式):
class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
//對象的必選參數(shù)
private final int servingSize;
private final int servings;
//對象的可選參數(shù)的缺省值初始化
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
//只用少數(shù)的必選參數(shù)作為構造器的函數(shù)參數(shù)
public Builder(int servingSize,int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
//使用方式
public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100)
.sodium(35).carbohydrate(27).build();
System.out.println(cocaCola);
}
(3)栗子
android中大量的使用對話框組件,它的調(diào)用方法就是構建域那,拼接咙边,表示。
Builder通過setTitle(),setMessage(),setIcon()等方法在create()中構造出一個AlertDialogInstance對象。
然后客戶可以把把AlertDialogInstance對象show出去败许。
附: Android用建造者模式實現(xiàn)一個新功能引導頁
(4)優(yōu)缺點
優(yōu):復用對象友瘤,避免不斷new構造者增加開銷;將很多功能集成到一個類里檐束,創(chuàng)造出比較復雜的東西辫秧。
6.原型模式
(1)理解
用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象被丧。
(2)類圖
略
注:克隆操作分深拷貝和淺拷貝盟戏,淺拷貝說白了就是把原對象所有的值和引用直接賦給新對象。深拷貝則不僅把原對象的值賦給新對象甥桂,而且會把原對象的引用對象也重新創(chuàng)建一遍再賦給新對象柿究。
(3)栗子
如Java的Cloneable接口。
使用場景:a.對象的創(chuàng)建非常復雜黄选,可以使用原型模式快捷的創(chuàng)建對象蝇摸。b.在運行過程中不知道對象的具體類型,可使用原型模式創(chuàng)建一個相同類型的對象办陷,或者在運行過程中動態(tài)的獲取到一個對象的狀態(tài)貌夕。
(4)優(yōu)缺點
缺:每個原型的子類都必須實現(xiàn)Cloneable接口,這個實現(xiàn)起來有時候比較困難民镜。
持續(xù)更新啡专,整理得不對的地方,還望指正制圈!
參考:
1.Java之美[從菜鳥到高手演變]之設計模式-終點
2.Android設計模式系列-謙虛天下
3.設計模式系列-Tony Chen
4.設計模式詳解-左瀟龍
5.設計模式UML類圖