什么是設計模式?詳解設計模式概念及幾大原則
第一節、前言
今天我們來講講設計模式,在我們學習Java的時候,時常聽到單例模式,多例模式,還有使用Spring的時候,默認采用的單例模式,你所聽到的“飽漢式”、“餓漢式”,都是對設計模式的形容。那么什么是設計模式呢?它又是什么概念呢。
第二節、設計模式概念與GOF設計模式
設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向對象的軟件開發人員所采用。設計模式是軟件開發人員在軟件開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟件開發人員經過相當長的一段時間的試驗和錯誤總結出來的。
個人理解:
設計模式并非是一種技術,而是在項目迭代的過程中,為了實現一些功能,設計了一些解決方案,將這些經驗進行總結出來的一個模式體系,這個體系是在被反復使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。
為什么要使用設計模式?
用設計模式是為了復用代碼、讓代碼更容易被他人理解、保證代碼可靠性。在目前的軟件設計潮流中,設計模式于己經應用與每個公司的各個項目中,設計模式使代碼編寫過程真正實現工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚一樣。項目中合理地運用設計模式可以完美地解決很多問題,每種模式在現實中都有相應的原理來與之對應,每種模式都描述了一個在我們在開發過程中、各個業務中相似的且又不斷重復發生的問題,以及提供了該問題的核心解決方案,這也是設計模式能被廣泛應用的原因。
GOF設計模式
可能有的朋友聽說過“GOF設計模式”,千萬不能認為GOF是一個人,更不要認為這些模式是他創寫的。GOF是一個四個人的小團隊,他們的名字全稱叫做“Gang of Four”,GOF設計模式是1994年這個團隊的4個人將在軟件開發中使用頻率較高的設計模式進行歸納,編寫成Design Patterns: Elements of Reusable Object-Oriented Software【《設計模式:可復用面向對象軟件的 基礎》】一書,該書的出版也標志著設計模式正式成為面向對象(Object Oriented)軟件工程的 一個重要研究分支。
第三節、設計模式六大原則及分類
講解GOF設計模式之前,我們先來了解下設計模式的六大原則:
- 開閉原則(Open Close Principle)
- 有開有閉原則,對擴展開放,但是對修改關閉。可以在程序需要拓展的時候使用,但是不能修改原有的代碼來實現擴展。
- 里氏代換原則(Liskov Substitution Principle)
任何基類可以出現的地方,子類一定可以出現。只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被復用,而派生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關系就是抽象化的具體實現。
可以理解為:子類可以擴展父類的功能,但不能改變原有父類的功能,例如:子類能夠替換父類在代碼中已出現的地方,且代碼替換以后,代碼還能正常工作。
- 依賴倒轉原則(Dependence Inversion Principle)
針對接口編程,依賴于抽象而不依賴于具體。簡單解釋就是面向接口編程,“抽象”就是接口或者抽象類,“具體”值得就是實現類;含義:上層模塊不應該依賴下層模塊,兩者應依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象;傳變量或者傳參數,盡量使用抽象類,或者接口。
例如:接口負責定義public的構造方法,抽象類負責公共構造部分的實現,實現類準確的實現業務邏輯。
- 接口隔離原則(Interface Segregation Principle)
使用多個相互隔離的接口開發,比使用單個接口要好。目的是為降低類之間的耦合度。
- 迪米特法則Demeter Principle)
最少知道原則,盡量降低類與類之間的耦合,一個實體應當盡量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立,防止高耦合度。
- 合成復用原則(Composite Reuse Principle)
它要求在軟件復用時,要盡量先使用組合或者聚合等關聯關系來實現,其次才考慮使用繼承關系來實現。如果要使用繼承關系,則必須嚴格遵循里氏代換原則。合成復用原則同里氏代換原則相輔相成的,兩者都是開閉原則的具體實現規范。合成復用原則是通過將已有的對象納入新對象中,作為新對象的成員對象來實現的,新對象可以調用已有對象的功能,從而達到復用。
程序設計目標:高內聚,低耦合
根據目的可以將設計模式被分為如下三種類型:
- 創建型模式:用于描述“怎樣創建對象”。
- 結構型模式:用于描述如何將類或對象按某種布局組成更大的結構。
- 行為型模式:用于描述類或對象之間怎樣相互協作共同完成某些單個對象都無法單獨完成的任務,以及怎樣分配職責。
根據作用范圍可以將設計模式分為兩類:
- 類模式:用于處理類與子類之間的關系,這些關系通過繼承來建立,是靜態的,在編譯時刻便確定下來了。
- 對象模式:用于處理對象之間的關系,這些關系可以通過組合或聚合來實現,在運行時刻是可以變化的,更具動態性。
第四節、學習認識類圖
認識UML類圖能更好的的學習設計模式,主流的設計模式都能夠通過UML類圖更加明亮清晰的展示類與類之間的關系;學會UML類圖也可以更快速的看懂類與類之間的關系。
什么是UML?
1) UML,全稱Unified modeling language UML (統一建模語言), 是一種用于軟件系統分析和設計的語言工具,它用于幫助軟件開發人員進行思考和記錄思路的結果。
2) UML 類似流程圖,本身有一套符號的規定,就像數學符號和化學符號一樣,這些符號用于描述軟件模型中的各個元素和他們之間的關系,比如類、接口、實現、泛化、依賴、組合、聚合等
常見的集中UML圖
你可能見過下面幾種UML圖:
用例圖
類圖
時序圖
UML圖可以簡單分為三類:
- 用例圖(use case)。
- 靜態結構圖:類圖、對象圖、包圖、組件圖、部署圖。
- 動態行為圖:交互圖(時序圖與協作圖)、狀態圖、活動圖。
我們主要學習類圖,那類圖是什么?
類圖(Class diagram)由許多(靜態)說明性的模型元素(例如類、包和它們之間的關系,這些元素和它們的內容互相連接)組成。類圖可以組織在(并且屬于)包中,僅顯示特定包中的相關內容。類圖(Class diagram)也是最常用的UML圖,顯示出類、接口以及它們之間的靜態結構和關系;它用于描述系統的結構化設計,類圖(Class diagram)最基本的元素是類或者接口。
類圖
類圖主要模型元素
- 類(Class)。
- 接口(Interface)。
- 類之間的關系。
一、類
類(Class)是指具有相同屬性、方法和關系的對象的抽象,它封裝了數據和行為,是面向對象程序設計(OOP)的基礎,具有封裝性、繼承性和多態性等三大特性。在 UML 中,類使用包含類名、屬性和操作且帶有分隔線的矩形來表示。
(1) 類名(Name):是一個字符串,例如,Student。
(2) 屬性(Attribute):是指類的特性,即類的成員變量。
UML 按以下格式表示:
- [可見性]屬性名:類型[=默認值]
- 例如:-name:String
注意:“可見性”表示該屬性對類外的元素是否可見,包括公有(Public)、私有(Private)、受保護(Protected)和朋友(Friendly,Java類圖中不適用此類型,其他語言可用)4 種,在類圖中分別用符號+、-、#、~表示
(3) 操作(Operations):是類的任意一個實例對象都可以使用的行為,是類的成員方法。UML 按以下格式表示:
- [可見性]名稱(參數列表)[:返回類型]
- 例如:+display():void
下圖所示是學生類的 UML 表示:
二、 接口
接口(Interface)是一種特殊的類,它具有類的結構,但不可被實例化,只可以被實現類實現。它包含抽象操作(抽象方法),但不包含屬性(成員變量),它描述了類或組件對外可見的動作。在 UML 中,接口使用一個帶有橫線小圓圈來進行表示。如下圖,類名左上方帶有橫線小圈的就是接口。
三、類之間的關系
類之間的關系有6種關系:依賴關系、關聯關系、聚合關系、組合關系、泛化關系、實現關系
每個關系之間的形狀配置如下:
1.依賴關系
依賴(Dependency)關系是一種使用關系,它是對象之間耦合度最弱的一種關聯方式,例如在Java中某個類的方法通過局部變量、方法的參數或者對靜態方法的調用來訪問另一個類(被依賴類)中的某些方法來完成一些業務開發。
依賴關系使用帶箭頭的虛線來表示,箭頭從使用類指向被依賴的類(被使用者),如下圖,所示是人與汽車的的關系圖,人通過汽車的run方法來完成駕駛。
2.關聯關系
關聯(Association)關系是對象之間的一種引用關系,用于表示一類對象與另一類對象之間的聯系;關聯可以是雙向的,也可以是單向的。在 UML 類圖中,雙向的關聯可以用帶兩個箭頭或者沒有箭頭的實線來表示,單向的關聯用帶一個箭頭的實線來表示,箭頭從使用類指向被關聯的類。也可以在關聯線的兩端標注角色名,代表兩種不同的角色。
(1)單向關聯,人擁有車的屬性對象。
(2)雙向關聯,人擁有汽車,汽車有歸屬人信息屬性
(3)自關聯,水由無數個水分子組成,但是水分子依然是水
3. 聚合關系
聚合(Aggregation)關系是關聯關系的一種,是強關聯關系,是整體和部分之間的關系,是 has-a 的關系;如果整體和部分單獨拿出來,也能變為獨立的模塊,但是整體需要依賴部分才能保證整體,在 UML 類圖中,聚合關系可以用帶空心菱形的實線來表示,菱形指向整體。
例如下圖:公司和員工每一個都是一個獨立的關系,如果公司沒有了,員工依然還是員工,但是所有員工都沒了,這個公司也就不復存在了。
4.組合關系
組合(Composition)關系也是關聯關系的一種,也表示類之間的整體與部分的關系,但它是一種更強烈的聚合關系,是 cxmtains-a 關系;在組合關系中,整體對象可以控制部分對象的生命周期,一旦整體對象不存在,部分對象也將不存在,部分對象不能脫離整體對象而存在;在 UML 類圖中,組合關系用帶實心菱形的實線來表示,菱形指向整體。
例如下圖:腳是人的身體的重要組成部分,如果身體不存在了,那么腳也就不存在了,且部分不能脫離整體。
5.泛化關系
泛化(Generalization)關系是對象之間耦合度最大的一種關系,是父類與子類之間的關系,是一種繼承關系,是 is-a 的關系。用Java的理念可以認為:一個父類只要被子類繼承,那這個父類與子類的關系就叫“泛化關系”。在 UML 類圖中,泛化關系用帶空心三角箭頭的實線來表示,箭頭從子類指向父類。在代碼實現時,使用面向對象的繼承機制來實現泛化關系
例如下圖:人作為一個父類,可能有多個子類,作者有人的屬性且有自己特殊的“寫作”技能,讀者擁有“評論書籍”的技能,這樣就構成了泛化關系(人類與作者、人類與讀者都是泛化關系)。
6.實現關系
實現(Realization)關系是接口與實現類之間的關系。在這種關系中,實現類實現了接口中的抽象方法,類中的操作實現了接口中所聲明的所有的抽象操作。在 UML 類圖中,實現關系使用帶空心三角箭頭的虛線來表示,箭頭從實現類指向接口。
例如下圖:車是一個接口是一個規范,滿足能跑起來就可以,汽車和自行車都實現了“跑”這個方法,而汽車現在可以實現自動駕駛,就是在按照接口的規范實現了“run”方法,那么接口與實現類的關系就是實現關系。
第五節、結束語
GOF常見23種設計模式總結了目前主流的設計模式,其中由于簡單工廠模式比較容易實現,所以并未被收錄;接下來的一段時間,小編會帶領大家學習24種設計模式,講述每種設計模式的概念、畫類圖、應用場景,大家一起共同學習、共同成長。
本文轉載自微信公眾號「IT小白架構師之路」,可以通過以下二維碼關注。轉載本文請聯系IT小白架構師之路公眾號。