java設計模式(java設計模式有幾種)
設計模式大雜燴(24種設計模式的總結以及學習設計模式的幾點建議)

模式分類 & 傳送門 & 對比維度說明
設計原則: ?設計模式(總綱)
創建型: ?單例模式? ?簡單工廠模式? ?工廠方法模式? ?抽象工廠模式??建造者模式??原型模式
結構型: ?代理模式? ?適配器模式? ?裝飾器模式? ?橋接模式? ?組合模式? ?享元模式??外觀模式
行為型: ?觀察者模式? ?模板方法模式? ?命令模式? ?狀態模式? ?職責鏈模式? ?解釋器模式? ?中介者模式? ?訪問者模式? ?策略模式??備忘錄模式??迭代器模式
以上便是設計模式的分類以及各個模式的傳送門,可以看到其中行為型模式的個數為最多,結構型次之,創建型設計模式最少。
在寫這篇文章的時候,LZ考慮的最多的一個問題就是,從哪幾個維度去對比設計模式能讓大家更加清楚的看出各個設計模式的區別與聯系,思來想去,LZ決定從以下幾個維度去對比設計模式。
設計原則:描述每個設計模式都遵循了哪些設計原則,破壞了哪些設計原則。
常用場景:描述各個設計模式大部分情況下,都會在哪些場景下出現。
使用概率:主要指在普遍的工作當中,該設計模式出現的頻率,若是類庫或是開源框架提供的功能中包含該模式,則也會計算其頻率。
復雜度:特指一個設計模式在實現的時候的復雜度,主要的衡量標準是類的數量、類之間的耦合關系。
變化點:設計模式很大的一個意義在于容納變化,掌握一個設計模式的變化點是非常重要的一件事。
選擇關鍵點:當選擇使用一個設計模式的時候,指出最關鍵的選擇點在哪里。
逆鱗:龍有逆鱗,不可觸摸,同樣的,設計模式也有逆鱗,有些地方是不能碰的。
相關設計模式:與其它設計模式的關系。
創建型設計模式
單例模式
設計原則:無
常用場景:應用中有對象需要是全局的且唯一
使用概率:99.99999%
復雜度:低
變化點:無
選擇關鍵點:一個對象在應用中出現多個實例是否會引起邏輯上或者是程序上的錯誤
逆鱗:在以為是單例的情況下,卻產生了多個實例
相關設計模式
原型模式:單例模式是只有一個實例,原型模式每拷貝一次都會創造一個新的實例。
簡單工廠模式
設計原則:遵循單一職責、違背開閉原則
常用場景:需要在一堆產品中選擇其中一個產品
使用概率:99.99999%
復雜度:低
變化點:產品的種類
選擇關鍵點:一種產品是否可根據某個參數決定它的種類
逆鱗:工廠類不能正常工作
相關設計模式
工廠方法模式:工廠方法模式是簡單工廠模式的進一步抽象化,在這兩者之間做選擇,主要看將工廠進一步抽象化是否有必要,通常情況下,如果工廠的作用僅僅是用來制造產品,則沒必要使用工廠方法模式。
工廠方法模式
設計原則:遵循單一職責、依賴倒置、開閉原則
常用場景:一種場景是希望工廠與產品的種類對客戶端保持透明,給客戶端提供一致的操作,另外一種是不同的工廠和產品可以提供客戶端不同的服務或功能
使用概率:60%
復雜度:中低
變化點:工廠與產品的種類
選擇關鍵點:工廠類和產品類是否是同生同滅的關系
逆鱗:無
相關設計模式
抽象工廠模式:工廠方法模式與抽象工廠模式最大的區別在于,在工廠方法模式中,工廠創造的是一個產品,而在抽象工廠模式中,工廠創造的是一個產品族。
抽象工廠模式
設計原則:遵循單一職責、依賴倒置、開閉原則
常用場景:需要一個接口可以提供一個產品族,且不必知道產品的具體種類
使用概率:30%
復雜度:中
變化點:工廠與產品的種類
選擇關鍵點:產品族是否需要一起提供,且是否有一致的接口
逆鱗:無
相關設計模式
建造者模式:兩者都是建造一批對象或者說產品,不同的是兩者的目的和實現手段,在建造者模式中,是為了復用對象的構建過程而定義了一個指揮者,而在抽象工廠模式中,是為了提供一個這批對象的創建接口而定義了抽象工廠接口。
建造者模式
設計原則:遵循單一職責、開閉原則
常用場景:需要構建一批構建過程相同但表示不同的產品,而構建過程非常復雜
使用概率:10%
復雜度:中
變化點:產品的表示
選擇關鍵點:各個產品的構建過程是否相同
逆鱗:指揮者不能正常工作
https://www.cnblogs.com/snailclimb/p/builderpattern.html
原型模式
設計原則:無
常用場景:需要在運行時動態的創建指定實例種類的對象,或是需要復用其狀態
使用概率:10%
復雜度:中低
變化點:無
選擇關鍵點:創建出來的對象是否可以立即投入使用
逆鱗:在以為是深度拷貝的情況下,卻未實現深度拷貝
結構型設計模式
代理模式
設計原則:體現功能復用
常用場景:需要修改或屏蔽某一個或若干個類的部分功能,復用另外一部分功能,可使用靜態代理,若是需要攔截一批類中的某些方法,在方法的前后插入一些一致的操作,假設這些類有一致的接口,可使用JDK的動態代理,否則可使用cglib
使用概率:99.99999%
復雜度:中高
變化點:靜態代理沒有變化點,動態代理的變化點為具有相同切入點的類
選擇關鍵點:靜態代理選擇的關鍵點是是否要復用被代理的部分功能,動態代理選擇的關鍵點在于能否在將被代理的這一批類當中,找出相同的切入點
逆鱗:切入點的不穩定
相關設計模式
適配器模式:對于適配器模式當中的定制適配器,它與靜態代理有著相似的部分,二者都有復用功能的作用,不同的是,靜態代理會修改一部分原有的功能,而適配器往往是全部復用,而且在復用的同時,適配器還會將復用的類適配一個接口
適配器模式
設計原則:遵循開閉原則、體現功能復用
常用場景:需要使用一個類的功能,但是該類的接口不符合使用場合要求的接口,可使用定制適配器,又或者是有一個接口定義的行為過多,則可以定義一個缺省適配器,讓子類選擇性的覆蓋適配器的方法
使用概率:40%
復雜度:中
變化點:無
選擇關鍵點:定制適配器的選擇關鍵點在于是否有更加優良的替代方案,缺省適配器的選擇關鍵點在于接口中的方法是否可以不全部提供,且都有缺省方案
逆鱗:無
相關設計模式
裝飾器模式:對于適配器模式中的定制適配器與裝飾器模式,二者都是使用組合加繼承的手段,不同的是,適配器模式的目的在于適配接口,裝飾器模式的目的在于動態的添加功能,且可以疊加。
https://www.cnblogs.com/Scott007/p/3439576.html
裝飾器模式
設計原則:遵循迪米特、單一職責、開閉原則,破壞里氏替換,體現功能復用
常用場景:一個類需要動態的添加功能,且這些功能可以相互疊加
使用概率:99.99999%
復雜度:中
變化點:動態添加的功能或者說裝飾器
選擇關鍵點:添加的功能是否需要動態組裝
逆鱗:無
橋接模式
設計原則:遵循單一職責、迪米特、開閉原則,體現功能復用
常用場景:一個對象有多個維度的變化,需要將這些維度抽離出來,讓其獨立變化
使用概率:20%
復雜度:中高
變化點:維度的擴展與增加
選擇關鍵點:是否可以將對象拆分成多個不相關的維度
逆鱗:無
組合模式
設計原則:遵循依賴倒置、開閉原則,破壞接口隔離
常用場景:當有一個結構可以組合成樹形結構,且需要向客戶端提供一致的操作接口,使得客戶端操作忽略簡單元素與復雜元素
使用概率:30%
復雜度:中
變化點:節點的數量
選擇關鍵點:對外提供一致操作接口的結構是否可轉化為樹形結構
逆鱗:結構不穩定或結構中的節點有遞歸關系
享元模式
設計原則:無
常用場景:一些狀態相同的對象被大量的重復使用
使用概率:90%
復雜度:中
變化點:無
選擇關鍵點:被共享的對象是否可以將外部狀態提取出來
逆鱗:沒有將外部狀態提取完全
外觀模式
設計原則:遵循迪米特
常用場景:一個子系統需要對外提供服務
使用概率:60%
復雜度:中
變化點:無
選擇關鍵點:子系統對外提供服務是否需要依賴很多的類
逆鱗:子系統對外提供的服務的變化或子系統本身的不穩定
相關設計模式
中介者模式:二者都是為了處理復雜的耦合關系,不同的是外觀模式處理的是類之間復雜的依賴關系,中介者模式處理的是對象之間復雜的交互關系
行為型設計模式
觀察者模式
設計原則:遵循迪米特、開閉原則
常用場景:需要將觀察者與被觀察者解耦或者是觀察者的種類不確定
使用概率:40%
復雜度:中
變化點:觀察者的種類與個數
選擇關鍵點:觀察者與被觀察者是否是多對一的關系
逆鱗:觀察者之間有過多的細節依賴
模板方法模式
設計原則:破壞里氏替換,體現功能復用
常用場景:一批子類的功能有可提取的公共算法骨架
使用概率:80%
復雜度:中低
變化點:算法骨架內各個步驟的具體實現
選擇關鍵點:算法骨架是否牢固
逆鱗:無
命令模式
設計原則:遵循迪米特、開閉原則
常用場景:行為的請求者與行為的處理者耦合度過高
使用概率:20%
復雜度:中高
變化點:命令的種類
選擇關鍵點:請求者是否不需要關心命令的執行只知道接受者
逆鱗:命令的種類無限制增長
相關設計模式
職責鏈模式:容易將二者關聯在一起的原因是,二者都是為了處理請求或者命令而存在的,而且二者都是為了將請求者與響應者解耦,不同的是命令模式中,客戶端需要知道一個命令的接受者,在創建命令的時候就把接受者與命令綁定在一起發送給調用者,而職責鏈模式中,客戶端并不關心最終處理請求的對象是誰,客戶端只是封裝一個請求對象,隨后交給職責鏈的頭部而已,也正因為這樣,二者的實現方式,有著很大的區別
狀態模式
設計原則:遵循單一職責、依賴倒置、開閉原則
常用場景:一個對象在多個狀態下行為不同,且這些狀態可互相轉換
使用概率:20%
復雜度:中
變化點:狀態的種類
選擇關鍵點:這些狀態是否經常在運行時需要在不同的動態之間相互轉換
逆鱗:無
相關設計模式
策略模式:二者的實現方式非常相似,策略接口與狀態接口,具體的策略與具體的狀態以及二者都擁有的上下文,如果看它們的類圖,會發現幾乎一模一樣,而二者不同的地方就在于,狀態模式經常會在處理請求的過程中更改上下文的狀態,而策略模式只是按照不同的算法處理算法邏輯,而且從實際場景來講,顧名思義,狀態模式改變的是狀態,策略模式改變的是策略
https://www.zhihu.com/question/23693088?sort=created
職責鏈模式
設計原則:遵循迪米特
常用場景:一個請求的處理需要多個對象當中的一個或幾個協作處理
使用概率:15%
復雜度:中
變化點:處理鏈的長度與次序
選擇關鍵點:對于每一次請求是否每個處理的對象都需要一次處理機會
逆鱗:無
解釋器模式
設計原則:遵循單一職責
常用場景:有一種語言被頻繁的使用
使用概率:0.00009%
復雜度:中高
變化點:語言的規則
選擇關鍵點:被頻繁使用的語言是否可用文法表示
逆鱗:語言的規則無限制增長或規則十分不穩定
中介者模式
設計原則:遵循迪米特,破壞單一職責
常用場景:一個系列的對象交互關系十分復雜
使用概率:10%
復雜度:中
變化點:對象之間的交互
選擇關鍵點:復雜的交互關系是否有共性可被中介者承擔
逆鱗:中介者無法工作
https://www.2cto.com/kf/201805/750094.html
訪問者模式
設計原則:遵循傾斜的開閉原則
常用場景:作用于一個數據結構之上的操作經常變化
使用概率:5%
復雜度:高
變化點:數據結構之上的操作
選擇關鍵點:數據結構是否穩定以及操作是否經常變化
逆鱗:數據結構的不穩定
策略模式
設計原則:遵循單一職責、依賴倒置、迪米特、開閉原則
常用場景:算法或者策略需要經常替換
使用概率:60%
復雜度:中
變化點:策略的種類
選擇關鍵點:客戶端是否依賴于某一個或若干個具體的策略
逆鱗:無
備忘錄模式
設計原則:遵循迪米特、開閉原則
常用場景:需要在對象的外部保存該對象的內部狀態
使用概率:5%
復雜度:中
變化點:無
選擇關鍵點:是否可以在必要的時候捕捉到對象的內部狀態
逆鱗:大對象的備份
迭代器模式
設計原則:遵循迪米特
常用場景:需要迭代訪問一個聚合對象中的各個元素,且不暴露該聚合對象內部的表示
使用概率:99.99999%
復雜度:中
變化點:聚合對象的種類
選擇關鍵點:客戶端是否關心遍歷的次序
逆鱗:無
相關設計模式
訪問者模式:二者都是迭代的訪問一個聚合對象中的各個元素,不同的是,訪問者模式中,擴展開放的部分在作用于對象的操作上,而迭代器模式中,擴展開放的部分在聚合對象的種類上,而且二者的實現方式也有著很大的區別。
結束語
以上便是24種設計模式的各個特點與部分模式的對比,如果總結的過程當中有疏漏或是錯誤,請各位不吝賜教,LZ感激不盡。
此外需要說明的是,上面的概率當中有的會出現99.99999%這樣的數字,這是因為這個模式已經嵌入到Java類庫或是我們常用的開源框架當中(標注一下:LZ總結的主要針對WEB開發,android的開發LZ并未接觸過,所以不包括在此列),比如迭代器模式,只要你使用過ArrayList或者HashSet,LZ就認為這個模式被使用。這個使用頻率從某種意義上講,可以認為是該模式的重要程度,當然由于這個頻率是LZ制定的,所以僅代表個人觀點。
這里再針對設計模式的學習,給各位提一點點建議,僅供參考,請各位吸優排差,次序不分先后。
1、之前說過,學習設計模式除了努力之外還要靠緣分,所以如果有設計模式當時怎么看都不明白,可以暫且放下,之后說不定哪天你突然之間就明白了。(此話并非虛言,LZ很多次的頓悟常發生在上廁所、洗澡、回家路上等一些學習之外的時候。)
2、對于已經在工作的人來說,可以常思考一下,有沒有哪個設計模式可以改善現有的系統架構,但不要輕易付諸實踐。
3、學習設計模式之前,一定要先整明白UML類圖,什么關聯,依賴,聚合,組合等等都得搞明白兒的,否則學習起來也依然會很吃力。
4、對于初學者,一定要在弄清楚標準的實現代碼之后,寫一個屬于自己的例子,哪怕是比葫蘆畫瓢,然后仔細體會設計模式使用前后的差異,主要從擴展性和類(類包括客戶端,而不僅僅指設計模式中的角色)的職責兩個方面。
5、一定要將設計模式的變化點搞清楚,這點非常重要,甚至重要程度高于設計模式的場景、實現方式以及類和對象之間的耦合關系,很多時候,設計模式的濫用就是因為變化點沒搞清楚,以至于該變化的沒變化,不該變化的經常變化,增加系統的負擔。
6、設計模式不是一次性學習完就可以扔掉不看的東西,而是要經常回過頭來看看,說不定每一次你都有不一樣的體會,而且一般情況下,這些體會會越來越深刻,越來越透徹。
7、如果可能的話,多研究一些開源框架,去找找它們里面的設計模式。
LZ暫時也就只能想到這些,如果以后有想到再補充吧,各位如果有什么好的建議也可以與LZ分享一下。
到此為止,整個設計模式系列就真真正正的徹底結束了,當初寫的時候也沒想到自己可以真的堅持下來,雖說整整26篇文章不算多,但是LZ確實花費了大量的時間和精力,值得欣慰的是LZ本人也得到了巨大的收獲,不僅僅是對設計模式的理解日益加深,而且還得了不少猿友的支持,讓LZ對分享這一道路更加堅定。
以后的編程之路還很長,對于LZ來說,編程并不僅僅是工作,而是一份事業,它給了LZ榮譽、金錢、成就感等等很多東西,希望各位至少在年輕的時候不要被一些悲觀化的觀點所干擾,特別是對編程有著熱愛的猿友們,極致才能成就大道,但凡在一個領域有所成就者,大都是鉆研了數十年的成果。
當然,人各有志,LZ無法左右他人,但LZ已經決定了自己的路,學火影里鳴人的一句話,“這就是我的忍道。”
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。