不知不覺,在開發這條道路上摸爬打滾也有些年頭了,偶爾回頭看看以前寫的代碼,真可謂粗糙至極,當然了,那時候還是小白,代碼寫得難看些情有可原,不過現在可不能再用以前的標準去衡量自己了,因此掌握一些高級架構技巧是必須的,設計模式正是一個很好的敲門磚,
在我看來,設計模式不僅僅只是一套模板,要想掌握設計模式并做到舉一反三,必須深入理解其中的思想,這個模式是為了解決什么問題?解決的思路是什么?代碼的實作又如何?如果問題細節發生了微小的變化又該如何處理?所以說思考很重要,不能死記硬背,一定要多想,
寫下這篇文章,是為了梳理自己的知識點,做個記錄,如果有來人看到了,并且對你有幫助的話,我也會很開心,因為知識是要傳播的,大家都樂于分享自己的見解,才能共同進步,
設計模式的定義
模式一詞起源于建筑業,描述了解決問題的核心方法,通過這種方式,可以多次重用那些已有的解決方案,無須重復相同的作業,
模式可以應用于不同的領域,軟體模式是將模式的一般概念應用于軟體開發領域,可以被認為是對軟體開發中某一特定問題的解法的某種統一表示,軟體模式并非僅限于設計模式,還包括架構模式、分析模式和程序模式等,在軟體生存期的每一個階段都存在著一些被認同的模式,
在軟體模式領域,目前研究最深入的是設計模式,設計模式是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結,使用這些設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性,
設計模式的基本要素
設計模式一般有如下幾個基本要素:模式名稱、問題、目的、解決方案、效果、實體代碼和其他相關設計模式,其中的關鍵元素包括以下四個方面:
模式名稱:通過一兩個詞來描述模式的問題、解決方案和效果,以更好地理解模式并方便開發人員之間的交流,
問題:描述了應該在何時使用模式,它包含了設計中存在的問題以及問題存在的原因,有時候問題描述可能會包含使用該模式時必須滿足的一系列先決條件,
解決方案:描述了設計模式的組成部分,以及這些組成部分之間的相互關系,各自職責和協作方式,解決方案并不描述一個特定而具體的設計或實作,而是提供設計問題的抽象描述和怎樣用一個具有一般意義的元素組合(類或者物件)來解決這個問題,
效果:描述模式應有的效果以及在使用模式時應權衡的問題,效果主要包含模式的優缺點分析,因此需要綜合考慮模式的效果,
設計模式的分類
設計模式一般有兩種分類方式,一種是根據目的分類(模式是用來做什么的),另一種則是根據范圍分類(模式是用來處理類之間的關系還是處理物件之間的關系),根據這兩種分類分別有如下兩張表供參考:
| 范圍\目的 | 創建型模式 | 結構型模式 | 行為型模式 |
|---|---|---|---|
| 類模式 | 工廠方法模式 | (類)配接器模式 | 解釋器模式 模板方法模式 |
| 物件模式 | 抽象工廠模式 建造者模式 原型模式 單例模式 |
(物件)配接器模式 橋接模式 組合模式 裝飾模式 外觀模式 享元模式 代理模式 |
職責鏈模式 命令模式 迭代器模式 中介者模式 備忘錄模式 觀察者模式 狀態模式 策略模式 訪問者模式 |
下面簡單對二十三種設計模式進行說明
| 模式類別 | 模式名稱 | 模式說明 |
|---|---|---|
| 創建型模式 | ||
| 抽象工廠模式 | 提供了一個創建一系列相關或相互依賴物件的介面,而無須指定它們具體的類 | |
| 工廠方法模式 | 該類的實體化操作延遲到子類中完成,即由子類來決定究竟該實體化(創建)哪一個類 | |
| 建造者模式 | 將一個復雜物件的構建與它的表示分離,使得同樣的構建程序可以創建不同的表示 | |
| 原型模式 | 通過給出一個原型物件來指明要創建物件的型別,然后通過復制這個原型物件來創建更多同型別的物件 | |
| 單例模式 | 確保在系統中某一個類只有一個實體,可以自行實體化并向整個系統提供這個實體 | |
| 結構型模式 | ||
| 配接器模式 | 將一個介面轉換成客戶希望的另一個介面,從而使介面不兼容的那些類可以一起作業 | |
| 橋接模式 | 將抽象部分與它的實作部分分離,使它們都可以獨立地變化 | |
| 組合模式 | 組合多個物件形成樹形結構以表示“整體-部分”的結構層次 | |
| 裝飾模式 | 動態地給一個物件增加一些額外的職責 | |
| 外觀模式 | 為復雜子系統提供一個一致的介面 | |
| 享元模式 | 通過運用共享技術有效地支持大量細粒度物件的復用 | |
| 代理模式 | 給某一個物件提供一個參考,并由代理物件控制對原物件的參考 | |
| 結構型模式 | ||
| 職責鏈模式 | 避免請求發送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連接成一條鏈,并且沿著這條鏈傳遞請求,直到有物件處理為止 | |
| 職責鏈模式 | 避免請求發送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連接成一條鏈,并且沿著這條鏈傳遞請求,直到有物件處理為止 | |
| 命令模式 | 將一個請求封裝為一個物件,從而使得請求呼叫者和請求接收者解耦 | |
| 解釋器模式 | 描述如何為語言定義一個語法,如何在該語言中表示一個句子,以及如何解釋這些句子 | |
| 迭代器模式 | 提供了一種方法來訪問聚合物件,而不用暴露這個物件的內部表示 | |
| 中介者模式 | 通過一個中介物件來封裝一系列的物件互動,使得各物件不需要顯式地相互參考,從而使其耦合松散,而且可以獨立地改變它們之間的互動 | |
| 備忘錄模式 | 在不破壞封裝的前提下,捕獲一個物件的內部狀態,并在該物件之外保存這個狀態,這樣可以在以后將物件恢復到原先保存的狀態 | |
| 觀察者模式 | 定義了物件間的一種一對多依賴關系,使得當每一個物件狀態發生改變時,其相關依賴物件皆得到通知并被自動更新 | |
| 狀態模式 | 允許將一個物件在其內部狀態改變時改變它的行為 | |
| 策略模式 | 定義一系列演算法,并將每一個演算法封裝在一個類中,讓它們可以相互替換,策略模式讓演算法獨立于使用它的客戶而變化 | |
| 模板方法模式 | 定義一個操作中演算法的骨架,而將一些步驟延遲到子類中 | |
| 訪問者模式 | 表示將一個作用于某物件結構中的各元素操作,它使得用戶可以在不改變各元素的類的前提下定義作用于這些元素的新操作 |
軟體設計模式修煉 -- 簡單工廠模式
軟體設計模式修煉 -- 工廠方法模式
軟體設計模式修煉 -- 抽象工廠模式
軟體設計模式修煉 -- 建造者模式
軟體設計模式修煉 -- 原型模式
軟體設計模式修煉 -- 單例模式
軟體設計模式修煉 -- 配接器模式
軟體設計模式修煉 -- 橋接模式
軟體設計模式修煉 -- 組合模式
軟體設計模式修煉 -- 裝飾模式
軟體設計模式修煉 -- 外觀模式
軟體設計模式修煉 -- 享元模式
軟體設計模式修煉 -- 代理模式
軟體設計模式修煉 -- 職責鏈模式
軟體設計模式修煉 -- 命令模式
軟體設計模式修煉 -- 解釋器模式
軟體設計模式修煉 -- 迭代器模式
軟體設計模式修煉 -- 中介者模式
軟體設計模式修煉 -- 備忘錄模式
軟體設計模式修煉 -- 觀察者模式
軟體設計模式修煉 -- 狀態模式
軟體設計模式修煉 -- 策略模式
軟體設計模式修煉 -- 模板方法模式
軟體設計模式修煉 -- 訪問者模式
以上就是設計模式的簡單介紹,下面是一些補充知識,如果已經掌握了可以不看,這些知識雖然不屬于設計模式范疇,但對于我們理解設計模式有莫大的好處,
統一建模語言
統一建模語言(UML)是一種可視化的標準建模語言,通過UML可以構造軟體系統的藍圖,在設計模式中,使用UML來分析和設計每一個模式的結構,描述每一個模式實體,幫助我們深入理解設計模式,
比如要蓋一棟房子,需要先設計圖紙,設計圖紙就是一種設計語言,也就是模型語言,在一個現代化工程中,人們要溝通和協作,就必須使用標準的工業化設計語言,通過建模進行描述,把所要設計的結構和系統的行為聯系起來,對系統的結構進行可視化控制,
UML 結構
UML 是由圖形符號表達的建模語言,其主要包括以下幾個部分:
視圖
使用不同的視圖從不同角度來描述軟體系統,包括:
用戶視圖:以用戶觀點表示系統的目標,它是所有視圖的核心,該視圖描述系統的需求
結構視圖:表示系統的靜態行為和靜態元素,如包、類與物件,以及它們之間的關系
行為視圖:表示系統的動態行為,描述組成元素如物件在系統運行時的互動關系
實作視圖:表示系統中邏輯元素的分布,描述系統中物理檔案以及它們之間的關系
環境視圖:表示系統中物理元素的分布,描述系統中硬體設備以及它們之間的關系
圖
提供了十三種與上述五種視圖相對,在設計模式的學習中,重點關注類圖、順序圖和狀態圖即可,
用例圖:對應用戶視圖,在用例圖中,使用用例來表示系統的功能需求,用例圖表示多個外部執行者與系統用例之間以及用例與用例之間的關系,
類圖:對應于結構視圖,類圖使用類來描述系統的靜態結構,類圖包括類和它們之間的關系,
物件圖:對應于結構視圖,物件圖用于表示類的物件實體之間的關系,
包圖:對應于結構視圖,描述包與包之間的關系,
組合結構圖:對應于結構視圖,表示一個類的內部結構,
狀態圖:對應于行為視圖,描述一系列物件的狀態及狀態之間的轉換,
活動圖:對應于行為視圖,表示系統中各種活動的次序,
順序圖:又稱時序圖或序列圖,對應于行為視圖,表示對互動,重點表示物件之間發送訊息的時間順序,
定時圖:對應于行為視圖,定時圖采用一種帶數字刻度的時間軸來描述訊息的順序,相比順序圖來說更加精確,
互動概覽圖:對應于行為視圖,可以把互動概覽圖理解為細化的活動圖,在其中的活動都通過一些小型的順序圖來表示,
組件圖:又稱構件圖,對應于實作視圖,描述每個功能所在組件位置以及它們之間的位置,
部署圖:又稱實施圖,對應于環境視圖,描述軟體中各個組件駐留的硬體位置以及這些硬體之間的互動關系,
模型元素
模型元素包括事物以及事物之間的聯系,事物代表任何可以定義的東西,事物之間的關系把事物聯系在一起,組成有意義的結構模式
通信機制
為模型元素提供額外的注釋、修飾和語意,
面向物件設計原則
面向物件設計原則是學習設計模式的基礎,每一種設計模式都符合某一種或多種面向物件設計原則,在軟體開發中使用這些原則可以提高軟體的可維護性和可復用性,讓我們可以設計出更加靈活也更容易擴展的軟體設計,實作可維護性復用的目標,
單一職責原則
一個物件應該只包含單一的職責,并且該職責被完整地封裝在一個類中
一個類承擔的職責越多,被復用的可能性越小,并且相當于將這些職責耦合在一起,因此需要將這些職責進行分離,實作高內聚、低耦合的指導方針,
開閉原則
一個軟體物體應當對擴展開放,對修改關閉,也就是說在設計一個模塊,應當使這個模塊可以在不被修改的前提下被擴展,
在開閉原則的定義中,軟體物體可以是一個軟體模塊、一個由多個類組成的區域結構或一個類,
軟體的需求會隨著時間推移發生變化,如果軟體設計符合開閉原則,就可以在擴展時無須修改現有代碼,保證穩定性與延續性,
抽象化是滿足開閉原則的關鍵,通過定義一個相對穩定的抽象層,將不同的實作行為在具體實作層中實作,如果需要修改,無須改動抽象層,只需增加新的物體類來實作新的業務功能即可,
里氏代換原則
所有參考基類(父類)的地方必須能透明地使用其子類的物件,說白了就是:在軟體中如果能使用其基類物件,那么一定能使用其子類物件,把基類都替換成它的子類,程式不會產生任何錯誤,但反過來則不成立,如果一個軟體物體使用的是一個子類,那么它不一定能使用基類,
里氏代換原則是實作開閉原則的重要方式之一,在程式中盡量使用基型別別來定義物件,而在運行時再確定其子型別別,用子類物件來替代父類物件,
依賴倒轉原則
高層模塊不應該依賴低層模塊,它們都應該依賴抽象,抽象不應該依賴于細節,細節應該依賴于抽象,即代碼要依賴于抽象的類,而不依賴于具體的類,要針對介面編程,不要針對實作編程,
如果說開閉原則是面向物件設計的目標的話,那么依賴倒轉原則就是面向物件設計的主要手段,下面介紹依賴倒轉原則中經常提到的兩個概念,
類之間的耦合:在面向物件系統中,兩個類之間通常可以發生三種不同的耦合關系(依賴關系)
1. 零耦合關系:兩個類之間沒有任何耦合關系
2. 具體耦合關系:兩個具體類之間存在一個類對另一個具體類實體的直接參考
3. 抽象耦合關系:發生在一個具體類和抽象類之間,也可以發生在兩個抽象類之間,依賴倒轉原則要求客戶端依賴于抽象耦合,
依賴注入:簡單來說,依賴注入就是將一個類的物件傳入另一個類,注入時應該注入父類物件,而在程式運行時再通過子類物件來覆寫父類物件,依賴注入有三種方式
1. 構造注入:通過建構式注入實體變數
2. 設值注入:通過Setter方法注入實體變數
3. 介面注入:通過介面方法注入實體變數
介面隔離原則
一旦一個介面太大,則需要將它分割成一些更小的介面,使用該介面的客戶端僅需知道與之相關的方法即可,
這里的介面往往有兩種不同的含義:
一種是指一個型別所具有的方法的特征的集合,僅僅是邏輯上的概念,介面的劃分將直接帶來型別的劃分,此時可以把介面理解成角色,一個介面只代表一個角色,每個角色都有它特有的一個介面,此時這個原則叫做角色隔離原則,
另一種是指介面僅僅提高客戶端需要的行為,即所需的方法,介面應該盡量細化,介面中的方法進來少,每個介面只包含一個客戶端所需的角色,
合成復用原則
盡量使用組合物件,而不是繼承來達到復用的目的,通俗來說,合成復用原則就是指一個新的物件里通過關聯關系(包括組合關系和聚合關系)來使用一些已有物件,使之成為新物件的一部分;新物件通過委派呼叫已有物件的方法達到復用已有功能的目的,
通過繼承來實作復用很簡單,子類可以覆寫父類方法,易于擴展,但會破壞系統的封裝性,因為繼承會將基類的實作細節暴露給子類,這種復用又稱為“白箱復用”,
通過組合/聚合來復用是將一個類的物件作為另一個類的物件的一部分,新物件可以呼叫已有物件的功能,這種復用又稱為“黑箱復用”,
迪米特法則
指一個軟體物體應盡可能少的與其他物體發生相互作用,當一個模塊修改時,就會盡量少的影響其他模塊,這是對軟體物體之間通信的限制,它要求軟體物體之間通信的寬度和深度,
在迪米特法則中,對于一個物件,其朋友包括以下幾類:
當前物件本身(this)
以引數形式傳入到當前物件方法中的物件
當前物件的成員物件
如果當前物件的成員物件是一個集合,那么集合中的元素也都是朋友
當前物件所創建的物件
任何物件如果滿足上面的條件之一,就是當前物件的“朋友”,否則就是“陌生人”,
狹義的迪米特法則:如果兩個類之間不必彼此通信,那么這兩個類就不應當發生直接的相互作用,如果其中一個類需要呼叫另一個類的某一個方法的話,可以通過第三者轉發這個呼叫,狹義的迪米特法則可以降低類之間的耦合,但也會造成系統不同模塊之間通信效率降低,使得系統的不同模塊之間不容易協調,
廣義的迪米特法則:指物件之間的資訊流量、流向以及資訊的影響的控制,主要是對資訊隱藏的控制,資訊的隱藏可以使各個子系統之間脫耦,每一個模塊不依賴于其他模塊存在,因此每一個模塊都可以獨立地在其他地方使用,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/4553.html
標籤:設計模式
上一篇:原型模式
下一篇:設計模式(8) 組合模式
