1. 程式人生 > >【設計模式】第一篇:概述、耦合、UML、七大原則,詳細分析總結(基於Java)

【設計模式】第一篇:概述、耦合、UML、七大原則,詳細分析總結(基於Java)

![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/879cf035c7c044469f3589610c4ba7f8~tplv-k3u1fbpfcp-zoom-1.image) 迷茫了一週,一段時間重複的 CRUD ,著實讓我有點煩悶,最近打算將這些技術棧系列的文章先暫時擱置一下,開啟一個新的篇章《設計模式》,畢竟前面寫了不少 “武功招式” 的文章,也該提升一下內功了 # 一 設計模式概述 ## (一) 什麼是設計模式 設計模式,即Design Patterns,是指在軟體設計中,被反覆使用的一種程式碼設計經驗。使用設計模式的目的是為了可重用程式碼,提高程式碼的可擴充套件性和可維護性 > 1995年,GoF(Gang of Four,四人組/四人幫)合作出版了《設計模式:可複用面向物件軟 > 件的基礎》一書,收錄了23種設計模式,從此樹立了軟體設計模式領域的里程碑,【GoF設計模式】 ## (二) 為什麼學習設計模式 前面我們學習了 N 種不同的技術,但是歸根結底,也只是 CRUD 與 呼叫之間的堆砌,或許這個創意亦或是業務很完善、很強大,其中也巧妙運用了各種高效的演算法,但是說白了,這也只是為了實現或者說解決某個問題而做的 還有時候,兩個人同時開發一款相同的產品,均滿足了預期的需求,但是 A 的程式,不僅**程式碼健壯性強**,同時**後期維護擴充套件更是便捷**(這種感覺,我們會在後面具體的設計模式中愈發的感覺到)而 B 的程式碼卻是一言難盡啊 有一句話總結的非常好: - **設計模式的本質是面向物件設計原則的實際運用,是對類的封裝性、繼承性和多型性以及類的關聯關係和組合關係的充分理解** 也就是說,畢竟像例如Java這樣面向物件的語言中,如何實現一個可維護,可維護的程式碼,那必然就是要降低程式碼耦合度,適當複用程式碼,而要實現這一切,就需要充分的利用 OOP 程式設計的特性和思想 注:下面第二大點補充【耦合】的相關概念,若不需要跳轉第三四大點【UML類圖及類圖間的關係】/【設計模式七大原則】 在之前我寫 Spring依賴注入的時候【萬字長文】 Spring框架層層遞進輕鬆入門(0C和D),就是從傳統開發,講到了如何通過工廠模式,以及多例到單例的改進,來一步步實現解耦,有興趣的朋友可以看一下哈 # 二 什麼是耦合?(高/低) 作為一篇新手都能看懂的文章,開始就一堆 IOC AOP等專業名詞扔出去,好像是不太禮貌,我得把需要鋪墊的知識給大家儘量說一說,如果對這塊比較明白的大佬,直接略過就OK了 耦合,就是模組間關聯的程度,每個模組之間的聯絡越多,也就是其耦合性越強,那麼獨立性也就越差了,所以我們在軟體設計中,應該儘量做到**低耦合**,高內聚 **生活中的例子**:家裡有一條串燈,上面有很多燈泡,如果燈壞了,你需要將整個燈帶都換掉,這就是高耦合的表現,因為燈和燈帶之間是緊密相連,不可分割的,但是如果燈泡可以隨意拆卸,並不影響整個燈帶,那麼這就叫做低耦合 **程式碼中的例子**:來看一個多型的呼叫,前提是 B 繼承 A,引用了很多次 ```java A a = new B(); a.method(); ``` 如果你想要把B變成C,就需要修改所有`new B()` 的地方為 `new C()` 這也就是高耦合 如果如果使用我們今天要說的 spring框架 就可以大大的降低耦合 ```java A a = BeanFactory().getBean(B名稱); a.method(); ``` 這個時候,我們只需要將B名稱改為C,同時將配置檔案中的B改為C就可以了 常見的耦合有這些分類: ## (一) 內容耦合 當一個模組直接修改或操作另一個模組的資料,或者直接轉入另一個模組時,就發生了內容耦合。此時,被修改的模組完全依賴於修改它的模組。 這種耦合性是很高的,最好避免 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ea18cb27ed3c400abdce61c6038e8751~tplv-k3u1fbpfcp-zoom-1.image) ```java public class A { public int numA = 1; } public class B { public static A a = new A(); public static void method(){ a.numA += 1; } public static void main(String[] args) { method(); System.out.println(a.numA); } } ``` ## (二) 公共耦合 兩個以上的模組共同引用一個全域性資料項就稱為公共耦合。大量的公共耦合結構中,會讓你很難確定是哪個模組給全域性變數賦了一個特定的值 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7347ab790e4e491691133599be3893ba~tplv-k3u1fbpfcp-zoom-1.image) ## (三) 外部耦合 一組模組都訪問同一全域性簡單變數,而且不通過引數表傳遞該全域性變數的資訊,則稱之為外部耦合 從定義和圖中也可以看出,公共耦合和外部耦合的區別就在於**前者是全域性資料結構**,**後者是全域性簡單變數** ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31d3f15287184558b3ac5896c5bdd66d~tplv-k3u1fbpfcp-zoom-1.image) ## (四) 控制耦合 控制耦合 。一個模組通過介面向另一個模組傳遞一個控制訊號,接受訊號的模組根據訊號值而進行適當的動作,這種耦合被稱為控制耦合,也就是說,模組之間傳遞的不是資料,而是一些標誌,開關量等等 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5222d3db86694fb19b45d84d1465581a~tplv-k3u1fbpfcp-zoom-1.image) ## (五) 標記耦合 標記耦合指兩個模組之間傳遞的是資料機構,如高階語言的陣列名、記錄名、檔名等這些名字即為標記,其實傳遞的是這個資料結構的地址 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/92dffa82406e44b4ab35a0bffb4dc813~tplv-k3u1fbpfcp-zoom-1.image) ## (六) 資料耦合 模組之間通過引數來傳遞資料,那麼被稱為資料耦合。資料耦合是最低的一種耦合形 式,系統中一般都存在這種型別的耦合,因為為了完成一些有意義的功能,往往需要將某些模組的輸出資料作為另 一些模組的輸入資料 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cbc4f295d413490c91046f57de3b2951~tplv-k3u1fbpfcp-zoom-1.image) ## (七) 非直接耦合 兩個模組之間沒有直接關係,它們之間的聯絡完全是通過主模組的控制和呼叫來實現的 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0d46ba12bc364304981adbf3eb05d898~tplv-k3u1fbpfcp-zoom-1.image) # 三 UML 類圖及類圖之間的關係 在一個相對完善的軟體系統中,每個類都有其責任,類與類之間,類與介面之間同時也存在著各種關係,UML(統一建模語言)從不同的角度定義了多種圖,在軟體建模時非常常用,下面我們說一下在設計模式中涉及相對較多的**類圖**,因為在後面單個設計模式的講解中,我們會涉及到,也算是一個基礎鋪墊。 ## (一) 類 類是一組相關的屬性和行為的集合,是一個抽象的概念,在UML中,一般用一個分為三層的矩形框來代表類 - 第一層:類名稱,是一個字串,例如 Student - 第二層:類屬性(欄位、成員變數)格式如下: - `[可見性]屬性名:型別[=預設值]` - 例如:-name:String - 第三層:類操作(方法、行為),格式如下: - `[可見性]名稱(引數列表)[:返回型別]` - 例如:+ display():void ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/872035288c854d32978976abc88ba8a6~tplv-k3u1fbpfcp-zoom-1.image) ## (二) 介面 介面,是一種特殊而又常用的類,不可被例項化,定義了一些抽象的操作(方法),但不包含屬性其實能見到介面 UML 描述的有三種形式: - 第一種:使用一個帶有名稱的小圓圈來表示,上面的Dog是介面名,下面是介面定義的方法 - 第二種:使用一個“框”來表示,和類很像,但是在最上面特別標註