從學程式設計一開始就被告知,要想做一名優秀的程式設計師兩大必要技能:1.原始碼閱讀(JDK、C等底層語言封裝) 2.設計模式(使用某種語言優雅的落地典型場景功能)。一般隨著工作年限的增長,被迫對底層語言/框架原始碼閱讀的越來愈多,但是設計模式如不刻意去學習,永遠不會真正掌握。筆者把設計模式比喻成程式設計師的「絕世神功」,掌握了設計模式,對快速閱讀原始碼、優雅地編寫程式有極大的促進作用,可以說就像打通了任督二脈一樣。
1995年,GoF(Gang of Four四人幫)合作出版了《設計模式:可複用物件導向軟體的基礎》(Design Patterns – Elements of Reusable Object-Oriented Software) 一書,書中總結了23種物件導向設計模式,也就是大名鼎鼎的GOF設計模式。
一直聽說有24種設計模式(網上一大堆標題24種設計模式,然後列舉的只有23種,也是無語),公認的GOF只有23種,還有一種是啥?大部分文章都說是簡單工廠模式(Simple Factory)。筆者搜遍全網(連chatGPT也問了),沒找到第24種設計模式誰提出的。這第24種設計模式,有說是簡單工廠模式,也有說是靜態工廠模式,也有說簡單工廠模式=靜態工廠模式,真是一塌糊塗,亂七八糟。神奇的是這些文章的作者都沒深究過這個問題,估計大都是拿來主義。
到底幾種?
---23種!!!即GOF的23種設計模式即可。還有2個模式:簡單工廠、靜態工廠,確實在後續應用比較多,但在1995年未列入GOF。
想要練成絕世武功,內功心法和外家套路缺一不可。要想練成「設計模式」這一絕世武功,「物件導向設計原則」就是內功心法(遵循的設計原則),「UML統一建模語言」就是外家套路(程式碼落地建模工具)。練功之前,咱們先簡單學習下這2個必備的基礎技能。
物件導向設計的目標之一就是支援可維護性複用,一方面需要實現設計方案的重用,另一方面要確保系統易於拓展和修改,具有較好的靈活性。7種物件導向設計原則,其中前5條是強約束性的建議都做到,後2條儘量做到即可。
1、單一職責原則(Single Responsibility Principle , SRP):一個物件應該只包含單一的職責,並且該職責被完整地封裝在一個類中。--單一職責原則是實現高內聚低耦合的指導方針。
理解:
2、開閉原則(Open Close Principle):對擴充套件開放,對修改關閉。--開閉原則是物件導向設計的目標。
理解:
3、里氏代換原則(Liskov Substitution Principle):所有參照基礎類別(父類別)的地方必須能透明地使用其子類的物件。--里氏代換原則是實現開閉原則的基礎。
4、依賴倒轉原則(Dependence Inversion Principle):高層模組不應該依賴低層模組,它們都應該依賴抽象。抽象不依賴於細節,細節應該依賴於抽象。--依賴倒轉原則就是物件導向設計的主要手段。
理解:
5、介面隔離原則(Interface Segregation Principle):使用者端不應該依賴那些它不需要的介面(方法),--介面級的單一職責原則。
理解:
6、迪米特法則(Demeter Principle):即最少知道原則,一個實體應當儘量少的與其他實體之間發生相互作用,減少耦合。
理解:
7、合成複用原則(Composite Reuse Principle):儘量使用合成/聚合的方式,而不是使用繼承,降低耦合。
理解:
UML1.X有9個圖,UML2.0有12個圖,具體如下圖所示:
一般,我們掌握 UML1.X 常用的9種圖即可,分為兩類:
本文需要使用靜態圖的一種:類圖。關注類圖中類之間的6種關係(耦合度大小排序):泛化 = 實現 > 組合 > 聚合 > 關聯 > 依賴。
本節列舉24種設計模式,其中建立型模式6種、結構型模式7種、行為型模式11種。每個模式從3個角度進行分析:定義、UML類圖、應用。
建立型模式,就是用來建立物件的。包含3塊:單例/原型模式、工廠模式(簡單工廠、工廠方法、抽象工廠)、建造者模式。
定義:保證一個類僅有一個範例,並提供一個存取它的全域性存取點。
UML類圖:
應用:待補充
定義:用原型範例指定建立物件的種類,並且通過拷貝這個原型來建立新的物件。
UML類圖:
定義:定義一個工廠類,使用static方法建立物件。根據不同引數返回不同範例,每增加一個物件需要修改工廠類,違背了「開閉原則」。--不推薦使用。
UML類圖:
應用:
定義:定義一個用於建立物件的介面,讓子類決定將哪一個類範例化。此模式使一個類的範例化延遲到其子類。
UML類圖:
應用:
定義:提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。用於建立一個產品族的產品。
UML類圖:
應用:
定義:將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
UML類圖:
應用:
定義:將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。
UML類圖:
應用:
Spring AOP中,org.springframework.aop.framework.adapter包下的AdvisorAdapter介面,有3個介面卡實現類:AfterReturningAdviceAdapter、MethodBeforeAdviceAdapter、ThrowsAdviceAdapter把每一個Advisor中的Advice都要適配成對應的MethodInterceptor物件。這裡使用的是方式二物件介面卡的變種。比如MethodBeforeAdviceAdapter介面卡通過getInterceptor()獲取到MethodBeforeAdviceInterceptor,最終結合攔截器模式(非GOF23),呼叫advice的advice.before()實現。
比較複雜,圖示如下:
定義:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
UML類圖:
拆出一個維度出來,進行聚合,可有效減少子類的個數。原本維度1個數*維度2個數->維度1個數的子類+維度2個數的聚合實現+1個聚合介面
應用:
java.sql包下的Driver和Connection介面,通過DriverManager進行橋接(不像圖中的聚合實現)。DriverManager定義了registerDriver和getConnection方法。registerDriver可以註冊各種驅動。Connection介面可實現連線多種資料庫。2個維度分開進行拓展實現,進行了脫耦。
定義:將物件組合成樹形結構以表示「部分-整體」的層次結構。它使得客戶對單個物件和複合物件的使用具有一致性。
UML類圖:
組合模式分為透明式(樹枝特有方法在抽象類中體現,樹葉類複寫空實現,使用者端使用時無需區分樹枝還是樹葉)和安全式(樹枝特有方法在樹枝類中體現)。當節點具有一致行為時採用透明式,當各節點行為不一致較多或樹枝節點較為健壯時採用安全式。
應用:
定義:動態地給一個物件新增一些額外的職責。就擴充套件功能而言, 它比生成子類方式更為靈活。
UML類圖:
應用:待補充
定義:為子系統中的一組介面提供一個一致的介面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
UML類圖:
應用:待補充
定義:運用共用技術有效地支援大量細粒度的物件。
UML類圖:
應用:待補充
定義:為其他物件提供一個代理以控制對這個物件的存取。
UML類圖:
應用:待補充
定義:解除請求的傳送者和接收者之間耦合,而使多個物件都有機會處理這個請求。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它。
UML類圖:
應用:待補充
定義:將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求紀錄檔,以及支援可取消的操作。
UML類圖:
應用:待補充
定義:給定一個語言, 定義它的文法的一種表示,並定義一個直譯器, 該直譯器使用該表示來解釋語言中的句子。
UML類圖:
應用:待補充
定義:提供一種方法順序存取一個聚合物件中各個元素,而又不需暴露該物件的內部表示。
UML類圖:
應用:待補充
定義:用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯式地相互參照,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
UML類圖:
應用:待補充
定義:在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態。這樣以後就可將該物件恢復到儲存的狀態。
UML類圖:
應用:待補充
定義:定義物件間的一種一對多的依賴關係,以便當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並自動重新整理。
UML類圖:
應用:觀察者模式
定義:允許一個物件在其內部狀態改變時改變它的行為。物件看起來似乎修改了它所屬的類。
UML類圖:
應用:待補充
定義:定義一系列的演演算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得演演算法的變化可獨立於使用它的客戶。
UML類圖:
應用:待補充
定義:定義一個操作中的演演算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個演演算法的結構即可重定義該演演算法的某些特定步驟。
UML類圖:
應用:待補充
定義:表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
UML類圖:
應用:待補充
===參考===================
如果你覺得本文對你有點幫助的話,記得在右下角點個「推薦」哦,博主在此感謝!