Head First 設計模式各模式思想及總結
阿新 • • 發佈:2019-02-17
雖然接觸設計模式很久了,但是以前沒有做筆記,也沒留下什麼程式碼,只怪當初太年輕呀~現在要重新回顧了。記住,設計模式注重的是思想,並不是具體實現,不要被設計模式限制了自己,也並不是我們寫程式碼一定要想著怎麼用設計模式來實現出來,按照設計模式的規範設計出來,一般情況下,把程式碼封裝好,把變化的東西封裝好,對外暴露不變的方法或介面,程式碼按照功能模組拆分成類和方法,做到這些已經可以讓後來看自己程式碼的人不罵自己了,哈哈哈,還是那句話,實際問題,實際解決。
一、設計模式的三大類
- 建立型模式: 主要解決物件建立例項化的問題,使得物件的建立解耦
- 工廠方法模式、抽象工廠模式、單例模式、生成器模式、原型模式
- 結構型模式: 解決類和類或類和物件如何結合在一起的問題,進而產生其他更有效用的功能結構
- 介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式
- 行為型模式: 解決類和類或類和物件之間溝通(呼叫)的問題,模式中主要體現的責任的劃分以及演算法的運用
- 策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式
二、各模式關鍵思想
- 工廠方法模式:體現為工廠方法介面,讓實現類去決定要生產哪種類的例項,常常需要傳引數進去,實現類判斷,然後在例項化
- 抽象工廠模式:連工廠都抽象出來了,抽象工廠裡面有一套的方法,規範實現類的行為,再用另外一個類來統一呼叫,這種方式開發的時候比較常見
- 單例模式:想辦法讓該類的例項在全域性只有唯一一個
- 生成器模式:這個千萬不要和模板方法搞混哦,這裡的主要思想是封裝例項構造過程,常常會傳入一些引數,然後會生成例項出來
- 原型模式:解決一個大的結構體裡面有各個小結構體會有不同變化的問題,體現了下面面向物件設計裡面的組合一些原理,小結構體被拆分為類,例項化後,傳進去大的結構體,大的結構體使用小的屬性來完成例項化
- 介面卡模式:按照現實中的電源介面卡或者其他轉換插頭來理解就好了,某個類呼叫後的返回值並不適合另外一個類的使用,這時候,構建一箇中間類來完成這個返回值的適配
- 組合模式:這個比較好理解,把多個物件組合起來,形成另外一個更加統一,功能更加豐富的類
- 裝飾器模式:JDK 裡面就有常用的了,流!往下就是輸入流輸出流,再往下就是檔案輸入流、位元組輸入流等,在流一層一層流動的過程中,不斷對流進行裝飾處理添油加醋的過程
- 代理模式:類似於景點門票代售點,去景點買和去代售點買是一樣的,區別在於能使呼叫物件方法的開銷減小;在 JDK中體現為 RMI
- 蠅量模式: 用於減少重複類的生成,把小物件(像蒼蠅一樣)抽象出來,成為一個獨立的類,在呼叫的時候告訴你這個類是長什麼樣的(屬性的值是多少),而不是在你例項化的時候就告訴你你長什麼樣,例項化之後就固定屬性了,所以在需要構造大量同一個物件,但是屬性會有差異的情況下,這個方法能大大提升系統性能
- 外觀模式:把某一些都需要呼叫的方法或屬性封裝起來,組合成為一個整體,使之成為一個類似一鍵XXX的功能
- 橋接模式:例如 classA 和 classB 有類似的功能,classC 想要任意呼叫 classA 和 classB,難道分別寫一套呼叫的邏輯嗎?不,橋接模式這時候有用了,寫一個橋接器,把 classA 和 classB 整合起來,只對外暴露相同的方法,外部只需要和橋接器對接就能夠任意呼叫 classA 和 classB 了。ps:萬能遙控
- 模板模式:某個類或者某個結構體裡面有一套程式執行的模板,會把這套模板過一遍,所以需要子類實現相應的方法,在 Java 中常常以抽象類的形式出現
- 直譯器模式:和程式的解析器差不多喇~在呼叫這個解析器的時候,會有一套語序和文法是和這個直譯器配套的,只有按照這個直譯器的規範來操作才能是直譯器正確執行
- 策略模式:根據實際情況,對程式碼進行抽象,把變化部分抽象出來介面 + 實現,以達到更好的程式碼複用效果
- 狀態模式:通過改變類的狀態而改變類的行為,例如執行緒裡面的等待狀態、執行狀態
- 觀察者模式:加入 classA 需要觀察 classB 的變化,那麼 classA 需要有有一個訂閱的過程,訂閱之後,classB 變化的時候就會通知 classB 有變化了,而不是 classA 隔一段時間去查詢 classB 有沒有變化,是一個主動變被動的關係,類似於回撥的機制
- 備忘錄模式:就像一個備忘錄的本子,你在裡面寫些什麼它不管你,你需要的時候翻開看看就行,體現比較多的地方應該是資料存檔了吧~
- 中介者模式:就拿售樓中介來舉例吧,所有的賣家如果要修改樓房資訊,告訴中介就行,中介這時候會公佈出來讓買家知道,起到一個溝通協調控制的作用,需要與代理模式以及橋接模式區別開來
- 命令模式:主要的思想還是抽象,把不變的封裝起來,可變的東西引數化,例如 linux 裡面的一個刪除命令 rm a.txt,可以變形成為 rm b.txt、而不是固定死要刪除 a.txt 的話只能用 rm a.txt,刪除 b.txt 的話就變成 del b.txt 了
- 訪問者模式:這個好像不太好理解,該模式重要的作用是方便對類屬性的訪問,主要通過雙重委託的方式 classA 中注入 classB 並呼叫 classB 的方法來實現對 classA 的訪問,如下圖,還需要藉助 Java 中抽象類的特性,使得繼承 Element 和 Visitor 的子類實現訪問的操作
- 責任鏈模式:加入有 classA、classB、classC 三個類,當 classD 執行一個操作有可能和前三個類都有關係的時候,先去問 classA,classA 反饋說“這不是我的責任”,然後回去問 classB,classA 說“這是我的責任啊,我來處理吧”,所以,把這個看做鏈結構,一級一級下去,就像平時的一家超市的商品出問題了,老闆會一級一級查下來,找出責任人
需要提一句,設計模式是建立在面向物件的基礎之上的,裡面每一種模式從命名到程式碼實現,都是面向物件的體現
三、面向物件設計的原則
- 組合複用原則:多用組合,少用繼承,在一個新的物件裡面使用一些已有的物件,達到複用的做效果
- 依賴倒置原則:實現類之間不發生直接的依賴關係,其依賴關係是通過介面或抽象類產生的;介面或抽象類不依賴實現類;實現類依賴介面或抽象類
- 開閉原則:核心思想是對於擴充套件是開放的,對於修改是關閉的,也就是說用抽象來封裝不變數,在功能升級或修改的時候,儘量用拓展的方式來實現
- 迪米特法則:也稱最少知道原則,在 Java 中體現較容易的就是 public、private 等控制作用域的關鍵字了,一些外界不應該知道或可以不知道的屬性或方法就隱藏起來
- 里氏替換原則:簡單理解,子類可以替換父類,所以要實現這個替換的話,子類就不能覆蓋父類的方法了,因為覆蓋的話,子類和父類呼叫相同的方法會有不同的結果
- 單一職責原則:每個類以及細化到每個方法,例如日期格式化,在其他地方儘量不要寫重複程式碼了,其作用盡可能單一,粒度儘量減小,但是伴隨而來的問題可能是類膨脹
上面無論哪種原則,其實都是為了程式執行得更好,以後拓展更加容易;這裡要想做得好,還是需要不斷重構程式碼才能真正提升程式設計能力,那麼《重構》這本書又要掉坑了,哈哈哈哈哈!總之想著我寫的程式碼,怎樣才能讓別人用得舒舒服服行~