Java設(shè)計(jì)模式之GOF23全面講解
一、什么是設(shè)計(jì)模式
設(shè)計(jì)模式(Design pattern) 是解決軟件開(kāi)發(fā)某些特定問(wèn)題而提出的一些解決方案也可以理解成解決問(wèn)題的一些思路。通過(guò)設(shè)計(jì)模式可以幫助我們?cè)鰪?qiáng)代碼的可重用性、可擴(kuò)充性、 可維護(hù)性、靈活性好。我們使用設(shè)計(jì)模式最終的目的是實(shí)現(xiàn)代碼的高內(nèi)聚和低耦合。
二、設(shè)計(jì)模式的三大分類(lèi)及關(guān)鍵點(diǎn)
1、創(chuàng)建型模式對(duì)象實(shí)例化的模式,創(chuàng)建型模式用于解耦對(duì)象的實(shí)例化過(guò)程。
單例模式:某個(gè)類(lèi)智能有一個(gè)實(shí)例,提供一個(gè)全局的訪問(wèn)點(diǎn)。工廠模式:一個(gè)工廠類(lèi)根據(jù)傳入的參量決定創(chuàng)建出哪一種產(chǎn)品類(lèi)的實(shí)例。抽象工廠模式:創(chuàng)建相關(guān)或依賴(lài)對(duì)象的家族,而無(wú)需明確指定具體類(lèi)。建造者模式:封裝一個(gè)復(fù)雜對(duì)象的創(chuàng)建過(guò)程,并可以按步驟構(gòu)造。原型模式:通過(guò)復(fù)制現(xiàn)有的實(shí)例來(lái)創(chuàng)建新的實(shí)例。 2、結(jié)構(gòu)型模式把類(lèi)或?qū)ο蠼Y(jié)合在一起形成一個(gè)更大的結(jié)構(gòu)。
裝飾器模式:動(dòng)態(tài)的給對(duì)象添加新的功能。代理模式:為其它對(duì)象提供一個(gè)代理以便控制這個(gè)對(duì)象的訪問(wèn)。橋接模式:將抽象部分和它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化。適配器模式:將一個(gè)類(lèi)的方法接口轉(zhuǎn)換成客戶(hù)希望的另一個(gè)接口。組合模式:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。外觀模式:對(duì)外提供一個(gè)統(tǒng)一的方法,來(lái)訪問(wèn)子系統(tǒng)中的一群接口。享元模式:通過(guò)共享技術(shù)來(lái)有效的支持大量細(xì)粒度的對(duì)象。 3、行為型模式類(lèi)和對(duì)象如何交互,及劃分責(zé)任和算法。
策略模式:定義一系列算法,把他們封裝起來(lái),并且使它們可以相互替換。模板模式:定義一個(gè)算法結(jié)構(gòu),而將一些步驟延遲到子類(lèi)實(shí)現(xiàn)。命令模式:將命令請(qǐng)求封裝為一個(gè)對(duì)象,使得可以用不同的請(qǐng)求來(lái)進(jìn)行參數(shù)化。迭代器模式:一種遍歷訪問(wèn)聚合對(duì)象中各個(gè)元素的方法,不暴露該對(duì)象的內(nèi)部結(jié)構(gòu)。觀察者模式:對(duì)象間的一對(duì)多的依賴(lài)關(guān)系。仲裁者模式:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互。備忘錄模式:在不破壞封裝的前提下,保持對(duì)象的內(nèi)部狀態(tài)。解釋器模式:給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器。狀態(tài)模式:允許一個(gè)對(duì)象在其對(duì)象內(nèi)部狀態(tài)改變時(shí)改變它的行為。責(zé)任鏈模式:將請(qǐng)求的發(fā)送者和接收者解耦,使的多個(gè)對(duì)象都有處理這個(gè)請(qǐng)求的機(jī)會(huì)。訪問(wèn)者模式:不改變數(shù)據(jù)結(jié)構(gòu)的前提下,增加作用于一組對(duì)象元素的新功能。
三、設(shè)計(jì)模式的幾種原則
1、單一職責(zé)原則
對(duì)于一個(gè)類(lèi),只有一個(gè)引起該類(lèi)變化的原因;該類(lèi)的職責(zé)是唯一的,且這個(gè)職責(zé)是唯一引起其他類(lèi)變化的原因。
2、接口隔離原則
客戶(hù)端不應(yīng)該依賴(lài)它不需要的接口,一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上。
3、依賴(lài)倒轉(zhuǎn)原則
依賴(lài)倒轉(zhuǎn)原則是程序要依賴(lài)于抽象接口,不要依賴(lài)于具體實(shí)現(xiàn)。簡(jiǎn)單的說(shuō)就是要求對(duì)抽象進(jìn)行編程,不要對(duì)實(shí)現(xiàn)進(jìn)行編程,這樣就降低了客戶(hù)與實(shí)現(xiàn)模塊間的耦合。
4、里式代換原則
任何基類(lèi)可以出現(xiàn)的地方,子類(lèi)一定可以出現(xiàn)。里氏代換原則是繼承復(fù)用的基石,只有當(dāng)衍生類(lèi)可以替換基類(lèi),軟件單位的功能不受影響時(shí),基類(lèi)才能真正的被復(fù)用,而衍生類(lèi)也能夠在基類(lèi)的基礎(chǔ)上增加新的行為。里氏代換原則是對(duì)開(kāi)閉原則的補(bǔ)充。實(shí)現(xiàn)開(kāi)閉原則的關(guān)鍵步驟就是抽象化。而基類(lèi)與子類(lèi)的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。
5、開(kāi)閉原則
(1)對(duì)于擴(kuò)展是開(kāi)放的(Open for extension)。這意味著模塊的行為是可以擴(kuò)展的。當(dāng)應(yīng)用的需求改變時(shí),我們可以對(duì)模塊進(jìn)行擴(kuò)展,使其具有滿(mǎn)足那些改變的新行為。也就是說(shuō),我們可以改變模塊的功能。
(2)對(duì)于修改是關(guān)閉的(Closed for modification)。對(duì)模塊行為進(jìn)行擴(kuò)展時(shí),不必改動(dòng)模塊的源代碼或者二進(jìn)制代碼。模塊的二進(jìn)制可執(zhí)行版本,無(wú)論是可鏈接的庫(kù)、DLL或者.EXE文件,都無(wú)需改動(dòng)。
6、迪米特法則
迪米特法則又叫做最少知識(shí)原則,就是說(shuō)一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其它對(duì)象又盡可能少的了解,不和陌生人說(shuō)話。
7、合成復(fù)用原則
合成復(fù)用原則要求在軟件復(fù)用時(shí),要盡量先使用組合或者聚合等關(guān)聯(lián)關(guān)系來(lái)實(shí)現(xiàn),其次才考慮使用繼承關(guān)系來(lái)實(shí)現(xiàn)。如果要使用繼承關(guān)系,則必須嚴(yán)格遵循里氏替換原則。合成復(fù)用原則同里氏替換原則相輔相成的,兩者都是開(kāi)閉原則的具體實(shí)現(xiàn)規(guī)范。
設(shè)計(jì)模式七大原則總結(jié)(超詳細(xì))
四、設(shè)計(jì)模式關(guān)系
五、設(shè)計(jì)模式感想
一共有23種設(shè)計(jì)模式,可以說(shuō)都是為了提高代碼的可讀性、可擴(kuò)展性、可復(fù)用性、類(lèi)的可替換性、組件化、可移植性等等特性。通過(guò)接口、抽象類(lèi)、繼承、實(shí)現(xiàn)、委托、抽象、面向接口編程、多態(tài)、重載、重寫(xiě)等方式使得代碼的這些特性得以彰顯,可以說(shuō)只有深刻的理解了這些概念背后的哲學(xué)思想才能更好的理解設(shè)計(jì)模式。在設(shè)計(jì)模式中有很多思想,比如可以使用委托的不要使用繼承、開(kāi)閉原則,面向擴(kuò)展開(kāi)放,面向修改關(guān)閉,里式代換原則,父類(lèi)一定能被子類(lèi)代替并使用,反置則不然,面向接口編程,功能層次和實(shí)現(xiàn)層次分離(橋接模式)、高內(nèi)聚低耦合等思想,這些思想都是寶貴的,正是因?yàn)檫@樣的思想的存在才使得代碼的更新?lián)Q代的時(shí)候能夠盡可能少的甚至不用修改之前的代碼,直接加入新的內(nèi)容。提高軟件的開(kāi)發(fā)周期,便于維護(hù)和升級(jí),便于查找和糾錯(cuò),易于擴(kuò)展和使用。
同樣的設(shè)計(jì)模式主要分為三大類(lèi),創(chuàng)建型、行為型、結(jié)構(gòu)型。我們可以簡(jiǎn)單的這樣分類(lèi),只不過(guò)這樣的分類(lèi)似乎并不準(zhǔn)確,不能一語(yǔ)道出所有的本質(zhì),設(shè)計(jì)模式是相互關(guān)聯(lián)的,有的設(shè)計(jì)模式內(nèi)部其實(shí)是使用了別的設(shè)計(jì)模式作為支撐的,但是大體上這樣的一種劃分便于我們?nèi)ビ洃?,僅此而已。
六、設(shè)計(jì)模式回顧
從迭代器開(kāi)始,我們將類(lèi)中數(shù)據(jù)結(jié)構(gòu)的遍歷和類(lèi)的功能實(shí)現(xiàn)分離出來(lái),本質(zhì)上使用了工廠模式;
其次我們學(xué)習(xí)了適配器模式,它將不同的接口進(jìn)行適配,從而便于版本的兼容性以及其他功能;
然后我們學(xué)習(xí)了模板方法,使用模板面向抽象編程,便于新的子類(lèi)的實(shí)現(xiàn)和管理;
之后學(xué)習(xí)了工廠模式,其實(shí)借用了模板模式來(lái)創(chuàng)建產(chǎn)品,是一種非常重要用處很廣的一種方法;
然后我們學(xué)習(xí)了單例模式,有懶漢式、餓漢式等,生成關(guān)于某個(gè)類(lèi)全局唯一的對(duì)象,注意多線程的影響;
之后是原型模式,用來(lái)復(fù)制復(fù)雜的對(duì)象,使用了clone方法,然后是builder模式,用一個(gè)新的類(lèi)對(duì)已有的抽象接口進(jìn)行整合和編程,從而構(gòu)建出我們想要的東西;
然后是抽象工廠模式,使用了工廠模式,組合模式等模式,面向抽象編程,將抽象零件組裝成抽象產(chǎn)品,便于具體工廠的創(chuàng)建,提高了代碼的組件化和復(fù)用性;
然后是橋接模式,將類(lèi)的功能層次和實(shí)現(xiàn)層次分割開(kāi)來(lái),便于對(duì)應(yīng)的擴(kuò)展和使用;
然后是策略模式,可以整體的替換策略,使用也很廣泛;然后是組合模式,保證了同根同源,通過(guò)委托添加自己構(gòu)成遞歸,樹(shù)形結(jié)構(gòu),將具有樹(shù)形特點(diǎn)的對(duì)象組合起來(lái);
然后是裝飾器模式,和組合模式的結(jié)構(gòu)類(lèi)似,同樣是遞歸結(jié)構(gòu),從而可以不斷的裝飾,增加新的功能,很好用;
接著是visitor訪問(wèn)者模式,通過(guò)在類(lèi)外訪問(wèn)類(lèi)中的數(shù)據(jù)結(jié)構(gòu)從而得到想要的結(jié)果,便于程序的可擴(kuò)展性和組件化;
接著是責(zé)任鏈模式,推卸責(zé)任,根據(jù)問(wèn)題的大小來(lái)考慮自己釋放處理,本質(zhì)是鏈表,便于職責(zé)分明;
然后是外觀模式,通過(guò)整合各個(gè)類(lèi)之間的調(diào)用關(guān)系,組建成了統(tǒng)一的接口(API),便于外部類(lèi)的調(diào)用;
接著是仲裁者模式,將很多類(lèi)之間互相關(guān)聯(lián)的關(guān)系交給仲裁者處理,省去了各個(gè)類(lèi)之間的嵌套和調(diào)動(dòng),有利于高內(nèi)聚和低耦合,思路清晰,便于擴(kuò)展;
然后是觀察者模式,通過(guò)互相委托從而能夠在被觀察的類(lèi)發(fā)生改變的時(shí)候得到相應(yīng)的改變的信息并且處理;
然后是備忘錄模式,通過(guò)在某一時(shí)刻的狀態(tài)保存下來(lái),便于恢復(fù),在游戲中使用的比較多;
然后是狀態(tài)模式,將狀態(tài)當(dāng)做類(lèi),從而職責(zé)分明,解除了很多繁瑣的if和else這些分支邏輯,便于擴(kuò)展;
然后是享元模式,輕量級(jí)對(duì)象,通過(guò)共用不變對(duì)象來(lái)實(shí)現(xiàn);
然后是代理模式,懶加載真正的服務(wù)器,加快訪問(wèn)速度,代理是幫助服務(wù)器代理的;
然后是命令模式,將命令當(dāng)做類(lèi),通過(guò)保存一些列命令,從而能夠隨時(shí)執(zhí)行這些命令,需要清除命令的本質(zhì)就是一些操作和數(shù)據(jù);
最后是解釋器模式,利用編程原理的方法,來(lái)更高層次的封裝代碼,將自己開(kāi)發(fā)的java代碼當(dāng)做編譯系統(tǒng),從而不用改變java代碼只修改更高語(yǔ)言層次的代碼就能實(shí)現(xiàn)不同的功能。
到此這篇關(guān)于Java設(shè)計(jì)模式之GOF23全面講解的文章就介紹到這了,更多相關(guān)Java設(shè)計(jì)模式講解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java request.getHeader("user-agent")獲取瀏覽器信息的方法
這篇文章主要介紹了java request.getHeader("user-agent")獲取瀏覽器信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03淺析Bean?Searcher?與?MyBatis?Plus?區(qū)別介紹
Bean?Searcher號(hào)稱(chēng)任何復(fù)雜的查詢(xún)都可以一行代碼搞定,但?Mybatis?Plus?似乎也有類(lèi)似的動(dòng)態(tài)查詢(xún)功能,最近火起的?Bean?Searcher?與?MyBatis?Plus?倒底有啥區(qū)別?帶著這個(gè)問(wèn)題一起通過(guò)本文學(xué)習(xí)下吧2022-05-05Java利用ITextPdf庫(kù)生成PDF預(yù)覽文件的具體實(shí)現(xiàn)
這篇文章主要給大家介紹了Java利用ITextPdf庫(kù)生成PDF預(yù)覽文件的具體實(shí)現(xiàn),文中通過(guò)代碼示例和圖文給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-04-04Java中的日期時(shí)間類(lèi)實(shí)例詳解(Date、Calendar、DateFormat)
在JDK1.0中,Date類(lèi)是唯一的一個(gè)代表時(shí)間的類(lèi),但是由于Date類(lèi)不便于實(shí)現(xiàn)國(guó)際化,所以從JDK1.1版本開(kāi)始,推薦使用Calendar類(lèi)進(jìn)行時(shí)間和日期處理,這篇文章主要介紹了Java中的日期時(shí)間類(lèi)詳解(Date、Calendar、DateFormat),需要的朋友可以參考下2023-11-11springboot項(xiàng)目啟動(dòng),但是訪問(wèn)報(bào)404錯(cuò)誤的問(wèn)題
這篇文章主要介紹了springboot項(xiàng)目啟動(dòng),但是訪問(wèn)報(bào)404錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12IntelliJ?IDEA設(shè)置JVM運(yùn)行參數(shù)的圖文介紹
這篇文章主要介紹了IntelliJ?IDEA設(shè)置JVM運(yùn)行參數(shù)的方法,包括配置方式及優(yōu)先級(jí),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04Java中HTTP GET方法調(diào)用帶有body的問(wèn)題解決
這篇文章主要為大家詳細(xì)介紹了Java如何解決HTTP GET方法調(diào)用帶有body的問(wèn)題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-02-02Netty網(wǎng)絡(luò)編程實(shí)戰(zhàn)之開(kāi)發(fā)聊天室功能
這篇文章主要為大家詳細(xì)介紹了如何利用Netty實(shí)現(xiàn)聊天室功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Netty網(wǎng)絡(luò)編程有一定幫助,需要的可以參考一下2022-10-10