23種設(shè)計(jì)模式總結(jié)詳解(全23種)
java的設(shè)計(jì)模式大體上分為三大類(lèi):
創(chuàng)建型模式(5種):工廠(chǎng)方法模式,抽象工廠(chǎng)模式,單例模式,建造者模式,原型模式。
結(jié)構(gòu)型模式(7種):適配器模式,裝飾器模式,代理模式,外觀(guān)模式,橋接模式,組合模式,享元模式。
行為型模式(11種):策略模式、模板方法模式、觀(guān)察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪(fǎng)問(wèn)者模式、中介者模式、解釋器模式。
設(shè)計(jì)模式遵循的原則有6個(gè):
1、開(kāi)閉原則(Open Close Principle)
? ? ??對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。
2、里氏代換原則(Liskov Substitution Principle)
? ? ??只有當(dāng)衍生類(lèi)可以替換掉基類(lèi),軟件單位的功能不受到影響時(shí),基類(lèi)才能真正被復(fù)用,而衍生類(lèi)也能夠在基類(lèi)的基礎(chǔ)上增加新的行為。
3、依賴(lài)倒轉(zhuǎn)原則(Dependence Inversion Principle)
? ? ??這個(gè)是開(kāi)閉原則的基礎(chǔ),對(duì)接口編程,依賴(lài)于抽象而不依賴(lài)于具體。
4、接口隔離原則(Interface Segregation Principle)
? ? ??使用多個(gè)隔離的借口來(lái)降低耦合度。
5、迪米特法則(最少知道原則)(Demeter Principle)
? ? ??一個(gè)實(shí)體應(yīng)當(dāng)盡量少的與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對(duì)獨(dú)立。
6、合成復(fù)用原則(Composite Reuse Principle)
? ? ??原則是盡量使用合成/聚合的方式,而不是使用繼承。繼承實(shí)際上破壞了類(lèi)的封裝性,超類(lèi)的方法可能會(huì)被子類(lèi)修改。
1.單例模式:確保某一個(gè)類(lèi)只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。
(1)懶漢式
(2)餓漢式
使用場(chǎng)景:
1.要求生成唯一序列號(hào)的環(huán)境;
2.在整個(gè)項(xiàng)目中需要一個(gè)共享訪(fǎng)問(wèn)點(diǎn)或共享數(shù)據(jù),例如一個(gè)Web頁(yè)面上的計(jì)數(shù)器,可以不用把每次刷新都記錄到數(shù)據(jù)庫(kù)中,使用單例模式保持計(jì)數(shù)器的值,并確保是線(xiàn)程安全的;
3.創(chuàng)建一個(gè)對(duì)象需要消耗的資源過(guò)多,如要訪(fǎng)問(wèn)IO和數(shù)據(jù)庫(kù)等資源;
4.需要定義大量的靜態(tài)常量和靜態(tài)方法(如工具類(lèi))的環(huán)境,可以采用單例模式(當(dāng)然,也可以直接聲明為static的方式)。
2.工廠(chǎng)模式:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化哪一個(gè)類(lèi)。工廠(chǎng)方法使一個(gè)類(lèi)的實(shí)例化延遲到其子類(lèi)。
接口
工廠(chǎng)類(lèi)
使用場(chǎng)景:jdbc連接數(shù)據(jù)庫(kù),硬件訪(fǎng)問(wèn),降低對(duì)象的產(chǎn)生和銷(xiāo)毀
3.抽象工廠(chǎng)模式:為創(chuàng)建一組相關(guān)或相互依賴(lài)的對(duì)象提供一個(gè)接口,而且無(wú)須指定它們的具體類(lèi)。
相對(duì)于工廠(chǎng)模式,我們可以新增產(chǎn)品類(lèi)(只需要實(shí)現(xiàn)產(chǎn)品接口),只需要同時(shí)新增一個(gè)工廠(chǎng)類(lèi),客戶(hù)端就可以輕松調(diào)用新產(chǎn)品的代碼。
使用場(chǎng)景:一個(gè)對(duì)象族(或是一組沒(méi)有任何關(guān)系的對(duì)象)都有相同的約束。涉及不同操作系統(tǒng)的時(shí)候,都可以考慮使用抽象工廠(chǎng)模式
4.建造者模式:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
使用場(chǎng)景:
1. 相同的方法,不同的執(zhí)行順序,產(chǎn)生不同的事件結(jié)果時(shí),可以采用建造者模式。
2.多個(gè)部件或零件,都可以裝配到一個(gè)對(duì)象中,但是產(chǎn)生的運(yùn)行結(jié)果又不相同時(shí),則可以使用該模式。
3.產(chǎn)品類(lèi)非常復(fù)雜,或者產(chǎn)品類(lèi)中的調(diào)用順序不同產(chǎn)生了不同的效能,這個(gè)時(shí)候使用建造者模式非常合適。
5.原型模式:用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。
原型模式實(shí)際上就是實(shí)現(xiàn)Cloneable接口,重寫(xiě)clone()方法。
使用原型模式的優(yōu)點(diǎn):
1.性能優(yōu)良
原型模式是在內(nèi)存二進(jìn)制流的拷貝,要比直接new一個(gè)對(duì)象性能好很多,特別是要在一個(gè)循環(huán)體內(nèi)產(chǎn)生大量的對(duì)象時(shí),原型模式可以更好地體現(xiàn)其優(yōu)點(diǎn)。
2.逃避構(gòu)造函數(shù)的約束
這既是它的優(yōu)點(diǎn)也是缺點(diǎn),直接在內(nèi)存中拷貝,構(gòu)造函數(shù)是不會(huì)執(zhí)行的。
使用場(chǎng)景:
1.資源優(yōu)化場(chǎng)景
類(lèi)初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)、硬件資源等。
2.性能和安全要求的場(chǎng)景
通過(guò)new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪(fǎng)問(wèn)權(quán)限,則可以使用原型模式。
3. 一個(gè)對(duì)象多個(gè)修改者的場(chǎng)景一個(gè)對(duì)象需要提供給其他對(duì)象訪(fǎng)問(wèn),而且各個(gè)調(diào)用者可能都需要修改其值時(shí),可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用。
淺拷貝和深拷貝:
淺拷貝:Object類(lèi)提供的方法clone只是拷貝本對(duì)象,其對(duì)象內(nèi)部的數(shù)組、引用對(duì)象等都不拷貝,還是指向原生對(duì)象的內(nèi)部元素地址,這種拷貝就叫做淺拷貝,其他的原始類(lèi)型比如int、long、char、string(當(dāng)做是原始類(lèi)型)等都會(huì)被拷貝。
注意: 使用原型模式時(shí),引用的成員變量必須滿(mǎn)足兩個(gè)條件才不會(huì)被拷貝:一是類(lèi)的成員變量,而不是方法內(nèi)變量;二是必須是一個(gè)可變的引用對(duì)象,而不是一個(gè)原始類(lèi)型或不可變對(duì)象。
深拷貝:對(duì)私有的類(lèi)變量進(jìn)行獨(dú)立的拷貝
如:this.arrayList = (ArrayList)this.arrayList.clone();
6.適配器模式:將一個(gè)類(lèi)的接口變換成客戶(hù)端所期待的另一種接口,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作
主要可分為3種:
1.類(lèi)適配:創(chuàng)建新類(lèi),繼承源類(lèi),并實(shí)現(xiàn)新接口,例如
2.對(duì)象適配:創(chuàng)建新類(lèi)持源類(lèi)的實(shí)例,并實(shí)現(xiàn)新接口,例如
3.接口適配:創(chuàng)建新的抽象類(lèi)實(shí)現(xiàn)舊接口方法。例如
使用場(chǎng)景:
你有動(dòng)機(jī)修改一個(gè)已經(jīng)投產(chǎn)中的接口時(shí),適配器模式可能是最適合你的模式。比如系統(tǒng)擴(kuò)展了,需要使用一個(gè)已有或新建立的類(lèi),但這個(gè)類(lèi)又不符合系統(tǒng)的接口,怎么辦?使用適配器模式,這也是我們例子中提到的。
7.裝飾器模式:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),裝飾器模式相比生成子類(lèi)更為靈活
使用場(chǎng)景:
1. 需要擴(kuò)展一個(gè)類(lèi)的功能,或給一個(gè)類(lèi)增加附加功能。
2. 需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能可以再動(dòng)態(tài)地撤銷(xiāo)。
3. 需要為一批的兄弟類(lèi)進(jìn)行改裝或加裝功能,當(dāng)然是首選裝飾模式。
8.代理模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪(fǎng)問(wèn)。
9.中介者模式:用一個(gè)中介對(duì)象封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯示地相互作用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。
使用場(chǎng)景:
中介者模式適用于多個(gè)對(duì)象之間緊密耦合的情況,緊密耦合的標(biāo)準(zhǔn)是:在類(lèi)圖中出現(xiàn)了蜘蛛網(wǎng)狀結(jié)構(gòu),即每個(gè)類(lèi)都與其他的類(lèi)有直接的聯(lián)系。
10.命令模式:將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓你使用不同的請(qǐng)求把客戶(hù)端參數(shù)化,對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,可以提供命令的撤銷(xiāo)和恢復(fù)功能。
Receiver接受者角色:該角色就是干活的角色,命令傳遞到這里是應(yīng)該被執(zhí)行的Command命令角色:需要執(zhí)行的所有命令都在這里聲明Invoker調(diào)用者角色:接收到命令,并執(zhí)行命令
使用場(chǎng)景:認(rèn)為是命令的地方就可以采用命令模式,例如,在GUI開(kāi)發(fā)中,一個(gè)按鈕的點(diǎn)擊是一個(gè)命令,可以采用命令模式;模擬DOS命令的時(shí)候,當(dāng)然也要采用命令模式;觸發(fā)-反饋機(jī)制的處理等。
11.責(zé)任鏈模式:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理它為止。
12.策略模式:定義一組算法,將每個(gè)算法都封裝起來(lái),并且使它們之間可以互換。
使用場(chǎng)景:
1. 多個(gè)類(lèi)只有在算法或行為上稍有不同的場(chǎng)景。
2. 算法需要自由切換的場(chǎng)景。
3. 需要屏蔽算法規(guī)則的場(chǎng)景。
13.迭代器模式:它提供一種方法訪(fǎng)問(wèn)一個(gè)容器對(duì)象中各個(gè)元素,而又不需暴露該對(duì)象的內(nèi)部細(xì)節(jié)。
迭代器模式已經(jīng)被淘汰,java中已經(jīng)把迭代器運(yùn)用到各個(gè)聚集類(lèi)(collection)中了,使用java自帶的迭代器就已經(jīng)滿(mǎn)足我們的需求了。
14.組合模式:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),使得用戶(hù)對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
使用場(chǎng)景:
1. 維護(hù)和展示部分-整體關(guān)系的場(chǎng)景,如樹(shù)形菜單、文件和文件夾管理。
2. 從一個(gè)整體中能夠獨(dú)立出部分模塊或功能的場(chǎng)景。
15.觀(guān)察者模式:定義對(duì)象間一種一對(duì)多的依賴(lài)關(guān)系,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴(lài)于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新。
使用場(chǎng)景:
1. 關(guān)聯(lián)行為場(chǎng)景。需要注意的是,關(guān)聯(lián)行為是可拆分的,而不是“組合”關(guān)系。
2. 事件多級(jí)觸發(fā)場(chǎng)景。
3. 跨系統(tǒng)的消息交換場(chǎng)景,如消息隊(duì)列的處理機(jī)制
16.門(mén)面模式:要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過(guò)一個(gè)統(tǒng)一的對(duì)象進(jìn)行。門(mén)面模式提供一個(gè)高層次的接口,使得子系統(tǒng)更易于使用。
使用場(chǎng)景:
1. 為一個(gè)復(fù)雜的模塊或子系統(tǒng)提供一個(gè)供外界訪(fǎng)問(wèn)的接口
2. 子系統(tǒng)相對(duì)獨(dú)立——外界對(duì)子系統(tǒng)的訪(fǎng)問(wèn)只要黑箱操作即可
3. 預(yù)防低水平人員帶來(lái)的風(fēng)險(xiǎn)擴(kuò)散
17.備忘錄模式:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可將該對(duì)象恢復(fù)到原先保存的狀態(tài)。
使用場(chǎng)景:
1. 需要保存和恢復(fù)數(shù)據(jù)的相關(guān)狀態(tài)場(chǎng)景。
2. 提供一個(gè)可回滾(rollback)的操作。
3. 需要監(jiān)控的副本場(chǎng)景中。
4. 數(shù)據(jù)庫(kù)連接的事務(wù)管理就是用的備忘錄模式。
18.訪(fǎng)問(wèn)者模式:封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作,它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。
使用場(chǎng)景:
1. 一個(gè)對(duì)象結(jié)構(gòu)包含很多類(lèi)對(duì)象,它們有不同的接口,而你想對(duì)這些對(duì)象實(shí)施一些依賴(lài)于其具體類(lèi)的操作,也就說(shuō)是用迭代器模式已經(jīng)不能勝任的情景。
2. 需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同并且不相關(guān)的操作,而你想避免讓這些操作“污染”這些對(duì)象的類(lèi)。
19.狀態(tài)模式:當(dāng)一個(gè)對(duì)象內(nèi)在狀態(tài)改變時(shí)允許其改變行為,這個(gè)對(duì)象看起來(lái)像改變了其類(lèi)。
使用場(chǎng)景:
1. 行為隨狀態(tài)改變而改變的場(chǎng)景
這也是狀態(tài)模式的根本出發(fā)點(diǎn),例如權(quán)限設(shè)計(jì),人員的狀態(tài)不同即使執(zhí)行相同的行為結(jié)果也會(huì)不同,在這種情況下需要考慮使用狀態(tài)模式。
2. 條件、分支判斷語(yǔ)句的替代者
20.解釋器模式:給定一門(mén)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
使用場(chǎng)景:
1. 重復(fù)發(fā)生的問(wèn)題可以使用解釋器模式
2. 一個(gè)簡(jiǎn)單語(yǔ)法需要解釋的場(chǎng)景
21.享元模式:使用共享對(duì)象的方法,用來(lái)盡可能減少內(nèi)存使用量以及分享資訊。
使用場(chǎng)景:
1. 系統(tǒng)中存在大量的相似對(duì)象。
2. 細(xì)粒度的對(duì)象都具備較接近的外部狀態(tài),而且內(nèi)部狀態(tài)與環(huán)境無(wú)關(guān),也就是說(shuō)對(duì)象沒(méi)有特定身份。
3. 需要緩沖池的場(chǎng)景。
22.橋梁模式:將抽象和實(shí)現(xiàn)解耦,使得兩者可以獨(dú)立地變化。
Circle類(lèi)將DrwaApi與Shape類(lèi)進(jìn)行了橋接,
使用場(chǎng)景:
1. 不希望或不適用使用繼承的場(chǎng)景
2. 接口或抽象類(lèi)不穩(wěn)定的場(chǎng)景
3. 重用性要求較高的場(chǎng)景
23.模板方法模式:定義一個(gè)操作中的算法的框架,而將一些步驟延遲到子類(lèi)中。使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
使用場(chǎng)景:
1. 多個(gè)子類(lèi)有公有的方法,并且邏輯基本相同時(shí)。
2. 重要、復(fù)雜的算法,可以把核心算法設(shè)計(jì)為模板方法,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè)子類(lèi)實(shí)現(xiàn)。
3. 重構(gòu)時(shí),模板方法模式是一個(gè)經(jīng)常使用的模式,把相同的代碼抽取到父類(lèi)中,然后通過(guò)鉤子函數(shù)(見(jiàn)“模板方法模式的擴(kuò)展”)約束其行為。