設計模式的總結有助於構建軟件開發知識體系,爲後期軟件的架構設計、重構打下夯實基礎,所以開設了Android設計模式專欄,後期會投入一定的精力深入學習和總結設計模式,並把相關理論知識與實際項目中用到的設計模式結合起來記錄於此,敬請關注和交流。
本文重在總結設計模式和設計原則,後期會結合具體實例代碼來說明常用的設計原則和設計模式。
文章目錄
- 一、概述
- 二、六大設計原則
- 2.1 單一職責原則(Single Responsibility Principle - SRP)
- 2.2 開放封閉原則(Open Closed Principle - OCP)
- 2.3 里氏替換原則(Liskov Substitution Principle - LSP)
- 2.4 最少知識原則(Least Knowledge Principle - LKP)
- 2.5 接口隔離原則(Interface Segregation Principle - ISP)
- 2.6 依賴倒置原則(Dependence Inversion Principle - DIP)
- 小結
- 三、其他設計原則
- 3.1 組合/聚合複用原則(Composition/Aggregation Reuse Principle - CARP)
- 3.2 無環依賴原則(Acyclic Dependencies Principle - ADP)
- 3.3 共同封裝原則(Common Closure Principle - CCP)
- 3.4 共同重用原則(Common Reuse Principle - CRP)
- 3.5 好萊塢原則(Hollywood Principle - HP)
- 3.6 不要重複你自己(Don't repeat yourself - DRY)
- 3.7 保持它簡單與傻瓜(Keep it simple and stupid - KISS)
- 3.8 高內聚與低耦合(High Cohesion and Low Coupling - HCLC)
- 3.9 慣例優於配置(Convention over Configuration - COC)
- 3.10 命令查詢分離(Command Query Separation - CQS)
- 3.11 關注點分離(Separation of Concerns - SOC)
- 3.12 契約式設計(Design by Contract - DBC)
- 3.13 你不需要它(You aren't gonna need it - YAGNI)
- 六大設計原則
- 設計模式口訣
一、概述
設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編制真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。
而設計原則則是設計模式所遵循的規則,設計模式就是實現了這些原則,從而達到了代碼複用、增加可維護性的目的。
二、六大設計原則
2.1 單一職責原則(Single Responsibility Principle - SRP)
一個類,只有一個引起它變化的原因。應該只有一個職責。每一個職責都是變化的一個軸線,如果一個類有一個以上的職責,這些職責就耦合在了一起。這會導致脆弱的設計。當一個職責發生變化時,可能會影響其它的職責。另外,多個職責耦合在一起,會影響複用性。例如:要實現邏輯和界面的分離。
2.2 開放封閉原則(Open Closed Principle - OCP)
軟件實體應該是可擴展,而不可修改的。也就是說,對擴展是開放的,而對修改是封閉的。
對擴展開放,意味着有新的需求或變化時,可以對現有代碼進行擴展,以適應新的情況。
對修改封閉,意味着類一旦設計完成,就可以獨立完成其工作,而不要對類進行任何修改。
封裝變化,是實現開放封閉原則的重要手段,對於經常發生變化的狀態一般將其封裝爲一個抽象。
拒絕濫用抽象,只將經常變化的部分進行抽象,這種經驗可以從設計模式的學習與應用中獲得。
2.3 里氏替換原則(Liskov Substitution Principle - LSP)
里氏替換原則通俗的來講就是:子類可以擴展父類的功能,但不能改變父類原有的功能。它包含以下4層含義:
- 子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
- 子類中可以增加自己特有的方法。
- 當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。
- 當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。
2.4 最少知識原則(Least Knowledge Principle - LKP)
最少知識原則又叫迪米特法則。核心思想是:低耦合、高內聚
一個實體應當儘量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。也就是說一個軟件實體應當儘可能少的與其他實體發生相互作用。這樣,當一個模塊修改時,就會盡量少的影響其他的模塊,擴展會相對容易,這是對軟件實體之間通信的限制,它要求限制軟件實體之間通信的寬度和深度。
2.5 接口隔離原則(Interface Segregation Principle - ISP)
接口隔離原則的含義是:建立單一接口,不要建立龐大臃腫的接口,儘量細化接口,接口中的方法儘量少。
採用接口隔離原則對接口進行約束時,要注意以下幾點:
- 接口儘量小,但是要有限度。對接口進行細化可以提高程序設計靈活性是不掙的事實,但是如果過小,則會造成接口數量過多,使設計複雜化。所以一定要適度。
- 爲依賴接口的類定製服務,只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地爲一個模塊提供定製服務,才能建立最小的依賴關係。
- 提高內聚,減少對外交互。使接口用最少的方法去完成最多的事情。
2.6 依賴倒置原則(Dependence Inversion Principle - DIP)
依賴倒置原則的核心思想是面向接口編程,不應該面向實現類編程。
在實際編程中,要做到下面3點:
- 低層模塊儘量都要有抽象類或接口,或者兩者都有。
- 變量的聲明類型儘量是抽象類或接口。
- 使用繼承時遵循里氏替換原則。
小結
-
Single Responsibility Principle單一職責原則
-
Open Closed Principe開閉原則
-
Liskov Substitution Principe裏式替換原則
-
Law of Demeter迪米特法則
-
Interface Segregation Principe接口隔離原則
-
Dependence Inversion Principe依賴倒置原則
把上面的六個原則的英文的首字母拿出來拼一下,就是SOLID(solid,穩定的),其代表的含義也就是把這六個結合使用的好處:建立穩定、靈活、健壯的設計,而開閉原則又是重中之重、最基礎的原則,是其他五大原則的精神領袖。
三、其他設計原則
除了以上六大設計原則之外。還有一些其他的設計原則,下面只做簡單介紹,
3.1 組合/聚合複用原則(Composition/Aggregation Reuse Principle - CARP)
當要擴展類的功能時,優先考慮使用組合,而不是繼承。這條原則在 23 種經典設計模式中頻繁使用,如:代理模式、裝飾模式、適配器模式等。可見江湖地位非常之高!
這也是面向對象中的一個重要原則。
3.2 無環依賴原則(Acyclic Dependencies Principle - ADP)
當 A 模塊依賴於 B 模塊,B 模塊依賴於 C 模塊,C 依賴於 A 模塊,此時將出現循環依賴。在設計中應該避免這個問題,可通過引入“中介者模式”解決該問題。
3.3 共同封裝原則(Common Closure Principle - CCP)
應該將易變的類放在同一個包裏,將變化隔離出來。該原則是“開放-封閉原則”的延生。
3.4 共同重用原則(Common Reuse Principle - CRP)
如果重用了包中的一個類,那麼也就相當於重用了包中的所有類,我們要儘可能減小包的大小。
3.5 好萊塢原則(Hollywood Principle - HP)
好萊塢明星的經紀人一般都很忙,他們不想被打擾,往往會說:Don’t call me, I’ll call you. 翻譯爲:不要聯繫我,我會聯繫你。對應於軟件設計而言,最著名的就是“控制反轉”(或稱爲“依賴注入”),我們不需要在代碼中主動的創建對象,而是由容器幫我們來創建並管理這些對象。
3.6 不要重複你自己(Don’t repeat yourself - DRY)
不要讓重複的代碼到處都是,要讓它們足夠的重用,所以要儘可能地封裝。
3.7 保持它簡單與傻瓜(Keep it simple and stupid - KISS)
不要讓系統變得複雜,界面簡潔,功能實用,操作方便,要讓它足夠的簡單,足夠的傻瓜。
3.8 高內聚與低耦合(High Cohesion and Low Coupling - HCLC)
模塊內部需要做到內聚度高,模塊之間需要做到耦合度低。
3.9 慣例優於配置(Convention over Configuration - COC)
儘量讓慣例來減少配置,這樣才能提高開發效率,儘量做到“零配置”。很多開發框架都是這樣做的。
3.10 命令查詢分離(Command Query Separation - CQS)
在定義接口時,要做到哪些是命令,哪些是查詢,要將它們分離,而不要揉到一起。
3.11 關注點分離(Separation of Concerns - SOC)
將一個複雜的問題分離爲多個簡單的問題,然後逐個解決這些簡單的問題,那麼這個複雜的問題就解決了。難就難在如何進行分離。
3.12 契約式設計(Design by Contract - DBC)
模塊或系統之間的交互,都是基於契約(接口或抽象)的,而不要依賴於具體實現。該原則建議我們要面向契約編程。
3.13 你不需要它(You aren’t gonna need it - YAGNI)
不要一開始就把系統設計得非常複雜,不要陷入“過度設計”的深淵。應該讓系統足夠的簡單,而卻又不失擴展性,這是其中的難點。
六大設計原則
- 單一職責原則
- 里氏替換原則
- 依賴倒置原則
- 接口隔離原則
- 迪米特法則(最少知道原則)
- 開閉原則
設計模式口訣
面向對象六大原則
六大原則 | ||
---|---|---|
接口隔離原則 | 單一職責原則 | 依賴倒轉原則 |
迪米特法則 | 里氏替換原則 | 開閉原則 |
創建型模式(5種)
創建型模式 | ||
---|---|---|
抽象工廠模式 | 工廠方法模式 | 建造者模式 |
單例模式 | 原型模式 |
結構型模式(7種)
結構型模式 | ||
---|---|---|
適配器模式 | 代理模式 | 橋接模式 |
組合模式 | 裝飾器模式 | 外觀模式 |
享元模式 |
行爲型模式(11種)
行爲型模式 | |||
---|---|---|---|
責任鏈模式 | 命令模式 | 中介者模式 | 解釋器模式 |
觀察者模式 | 迭代子模式 | 備忘錄模式 | 訪問者模式 |
狀態模式 | 策略模式 | 模板方法模式 |
記憶方法
類型 | 口訣 | 額外 |
---|---|---|
六個原則 | 接單依賴迪裏開 | 無 |
創建型模型 | 抽工建單元 | 無 |
結構型模型 | 與時代相結合,裝外向 時(適配器模式)代(代理模式)結(橋接模式)合(組合模式),裝(裝飾模式)外(外觀模式)向(享元模式); |
無 |
行爲型模型 | 責令中介觀疊被,防撞車 責(責任鏈模式)令(命令模式)中介(中介模式)觀察(觀察者模式)疊(迭代器模式)被(備忘錄模式),防(訪問者模式)撞(狀態模式)車(策略模式) |
模板方法模式 |
參考資料:
4.參考書籍《設計模式之禪》